about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock102
-rw-r--r--compiler/rustc_abi/Cargo.toml24
-rw-r--r--compiler/rustc_abi/src/layout.rs947
-rw-r--r--compiler/rustc_abi/src/lib.rs1399
-rw-r--r--compiler/rustc_arena/src/tests.rs16
-rw-r--r--compiler/rustc_ast/src/ast.rs4
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs9
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs3
-rw-r--r--compiler/rustc_ast/src/visit.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs32
-rw-r--r--compiler/rustc_ast_lowering/src/block.rs10
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs216
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs181
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs122
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs54
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs8
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs228
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs10
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs15
-rw-r--r--compiler/rustc_borrowck/src/places_conflict.rs14
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs1
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs16
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/utils.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/config.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs30
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs21
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs4
-rw-r--r--compiler/rustc_const_eval/src/util/call_kind.rs4
-rw-r--r--compiler/rustc_driver/src/lib.rs9
-rw-r--r--compiler/rustc_error_messages/locales/en-US/metadata.ftl2
-rw-r--r--compiler/rustc_errors/src/emitter.rs2
-rw-r--r--compiler/rustc_errors/src/lib.rs21
-rw-r--r--compiler/rustc_hir/src/def.rs22
-rw-r--r--compiler/rustc_hir/src/hir.rs34
-rw-r--r--compiler/rustc_hir/src/hir_id.rs14
-rw-r--r--compiler/rustc_hir/src/lang_items.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_method.rs101
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs53
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs41
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/explicit.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/variance/terms.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs15
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs51
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs15
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs63
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs30
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs29
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs37
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs9
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs2
-rw-r--r--compiler/rustc_incremental/src/persist/save.rs4
-rw-r--r--compiler/rustc_index/Cargo.toml8
-rw-r--r--compiler/rustc_index/src/lib.rs22
-rw-r--r--compiler/rustc_index/src/vec.rs7
-rw-r--r--compiler/rustc_infer/src/infer/at.rs1
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs13
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs31
-rw-r--r--compiler/rustc_infer/src/infer/equate.rs8
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs13
-rw-r--r--compiler/rustc_infer/src/infer/glb.rs9
-rw-r--r--compiler/rustc_infer/src/infer/lub.rs9
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs30
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs42
-rw-r--r--compiler/rustc_infer/src/infer/outlives/mod.rs1
-rw-r--r--compiler/rustc_infer/src/infer/outlives/test_type_match.rs9
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs9
-rw-r--r--compiler/rustc_infer/src/traits/engine.rs8
-rw-r--r--compiler/rustc_infer/src/traits/util.rs1
-rw-r--r--compiler/rustc_interface/src/interface.rs2
-rw-r--r--compiler/rustc_interface/src/queries.rs6
-rw-r--r--compiler/rustc_interface/src/util.rs7
-rw-r--r--compiler/rustc_lexer/src/unescape/tests.rs6
-rw-r--r--compiler/rustc_lint/src/builtin.rs1
-rw-r--r--compiler/rustc_lint/src/context.rs17
-rw-r--r--compiler/rustc_lint/src/deref_into_dyn_supertrait.rs92
-rw-r--r--compiler/rustc_lint/src/early.rs4
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/types.rs8
-rw-r--r--compiler/rustc_lint/src/unused.rs330
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs46
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp2
-rw-r--r--compiler/rustc_metadata/src/creader.rs2
-rw-r--r--compiler/rustc_metadata/src/errors.rs1
-rw-r--r--compiler/rustc_metadata/src/locator.rs9
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs36
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs63
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs2
-rw-r--r--compiler/rustc_middle/src/arena.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs8
-rw-r--r--compiler/rustc_middle/src/middle/limits.rs2
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs107
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs16
-rw-r--r--compiler/rustc_middle/src/query/keys.rs (renamed from compiler/rustc_query_impl/src/keys.rs)23
-rw-r--r--compiler/rustc_middle/src/query/mod.rs3
-rw-r--r--compiler/rustc_middle/src/thir.rs3
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs20
-rw-r--r--compiler/rustc_middle/src/traits/select.rs4
-rw-r--r--compiler/rustc_middle/src/traits/structural_impls.rs12
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs9
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs20
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs14
-rw-r--r--compiler/rustc_middle/src/ty/context.rs8
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs18
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs1
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs33
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs302
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs23
-rw-r--r--compiler/rustc_middle/src/ty/query.rs5
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs32
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs1
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs3
-rw-r--r--compiler/rustc_middle/src/ty/util.rs23
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/block.rs7
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs168
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs7
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs8
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs74
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs13
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs7
-rw-r--r--compiler/rustc_mir_build/src/build/matches/util.rs35
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs12
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs18
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs4
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs95
-rw-r--r--compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs2
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs12
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs12
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs13
-rw-r--r--compiler/rustc_parse/src/parser/item.rs38
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs12
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs16
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs6
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs6
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs9
-rw-r--r--compiler/rustc_query_impl/src/lib.rs3
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs2
-rw-r--r--compiler/rustc_query_system/src/query/caches.rs203
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs2
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs47
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs17
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs116
-rw-r--r--compiler/rustc_resolve/src/late.rs6
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs19
-rw-r--r--compiler/rustc_save_analysis/src/dump_visitor.rs2
-rw-r--r--compiler/rustc_session/src/config.rs8
-rw-r--r--compiler/rustc_session/src/session.rs9
-rw-r--r--compiler/rustc_span/src/lib.rs4
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs8
-rw-r--r--compiler/rustc_target/Cargo.toml1
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/sparc64.rs14
-rw-r--r--compiler/rustc_target/src/abi/mod.rs1330
-rw-r--r--compiler/rustc_target/src/lib.rs5
-rw-r--r--compiler/rustc_target/src/spec/aix_base.rs32
-rw-r--r--compiler/rustc_target/src/spec/mod.rs127
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs23
-rw-r--r--compiler/rustc_trait_selection/src/autoderef.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs38
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs44
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs63
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs44
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs88
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs94
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs2
-rw-r--r--compiler/rustc_traits/Cargo.toml1
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs30
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs10
-rw-r--r--compiler/rustc_traits/src/implied_outlives_bounds.rs30
-rw-r--r--compiler/rustc_traits/src/normalize_erasing_regions.rs1
-rw-r--r--compiler/rustc_ty_utils/Cargo.toml2
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs6
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs960
-rw-r--r--compiler/rustc_ty_utils/src/layout_sanity_check.rs18
-rw-r--r--library/alloc/benches/lib.rs2
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/tests/boxed.rs41
-rw-r--r--library/alloc/tests/fmt.rs13
-rw-r--r--library/alloc/tests/lib.rs2
-rw-r--r--library/alloc/tests/str.rs12
-rw-r--r--library/alloc/tests/vec.rs3
-rw-r--r--library/core/src/future/mod.rs27
-rw-r--r--library/core/src/primitive_docs.rs2
-rw-r--r--library/core/src/ptr/const_ptr.rs4
-rw-r--r--library/core/src/ptr/mut_ptr.rs4
-rw-r--r--library/core/src/str/mod.rs12
-rw-r--r--library/core/src/str/pattern.rs10
-rw-r--r--library/core/src/task/poll.rs1
-rw-r--r--library/std/src/lib.rs3
-rw-r--r--library/std/src/os/windows/io/socket.rs1
-rw-r--r--library/std/src/personality/dwarf/eh.rs7
-rw-r--r--library/std/src/primitive_docs.rs2
-rw-r--r--library/std/src/sys/sgx/mod.rs1
-rw-r--r--library/unwind/src/libunwind.rs5
-rw-r--r--src/bootstrap/Cargo.lock81
-rw-r--r--src/bootstrap/Cargo.toml2
-rw-r--r--src/bootstrap/builder.rs8
-rw-r--r--src/bootstrap/dist.rs4
-rw-r--r--src/bootstrap/doc.rs21
-rw-r--r--src/bootstrap/download.rs2
-rw-r--r--src/doc/rustc/src/platform-support.md1
-rw-r--r--src/doc/unstable-book/src/language-features/abi-efiapi.md23
-rw-r--r--src/librustdoc/clean/inline.rs2
-rw-r--r--src/librustdoc/clean/mod.rs15
-rw-r--r--src/librustdoc/clean/types.rs4
-rw-r--r--src/librustdoc/html/render/mod.rs20
-rw-r--r--src/librustdoc/html/render/print_item.rs46
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css17
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css8
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css10
-rw-r--r--src/librustdoc/html/static/css/themes/light.css9
-rw-r--r--src/librustdoc/html/templates/page.html1
-rw-r--r--src/librustdoc/json/conversions.rs10
-rw-r--r--src/test/codegen/async-fn-debug-awaitee-field.rs8
-rw-r--r--src/test/codegen/issue-37945.rs4
-rw-r--r--src/test/codegen/mem-replace-direct-memcpy.rs4
-rw-r--r--src/test/codegen/slice-iter-len-eq-zero.rs2
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.async2.txt4
-rw-r--r--src/test/run-make/rustdoc-verify-output-files/Makefile36
-rw-r--r--src/test/run-make/rustdoc-verify-output-files/src/lib.rs1
-rw-r--r--src/test/rustdoc-gui/search-result-display.goml3
-rw-r--r--src/test/rustdoc-gui/sidebar-source-code-display.goml44
-rw-r--r--src/test/rustdoc-gui/src/test_docs/lib.rs5
-rw-r--r--src/test/rustdoc-gui/struct-fields.goml5
-rw-r--r--src/test/ui/async-await/async-block-control-flow-static-semantics.stderr6
-rw-r--r--src/test/ui/async-await/async-borrowck-escaping-block-error.stderr20
-rw-r--r--src/test/ui/async-await/drop-tracking-unresolved-typeck-results.rs106
-rw-r--r--src/test/ui/async-await/drop-tracking-unresolved-typeck-results.stderr62
-rw-r--r--src/test/ui/async-await/generator-desc.stderr32
-rw-r--r--src/test/ui/async-await/issue-68112.drop_tracking.stderr4
-rw-r--r--src/test/ui/async-await/issue-68112.no_drop_tracking.stderr4
-rw-r--r--src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr5
-rw-r--r--src/test/ui/async-await/issues/issue-78938-async-block.stderr4
-rw-r--r--src/test/ui/async-await/try-on-option-in-async.stderr3
-rw-r--r--src/test/ui/binding/issue-53114-borrow-checks.stderr16
-rw-r--r--src/test/ui/binop/binop-move-semantics.stderr4
-rw-r--r--src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr25
-rw-r--r--src/test/ui/borrowck/borrowck-consume-unsize-vec.stderr12
-rw-r--r--src/test/ui/borrowck/borrowck-consume-upcast-box.stderr8
-rw-r--r--src/test/ui/borrowck/borrowck-drop-from-guard.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr40
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr36
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr56
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr36
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr56
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array.stderr40
-rw-r--r--src/test/ui/borrowck/borrowck-multiple-captures.stderr15
-rw-r--r--src/test/ui/borrowck/borrowck-overloaded-index-move-index.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-reinit.stderr5
-rw-r--r--src/test/ui/borrowck/issue-31287-drop-in-guard.stderr5
-rw-r--r--src/test/ui/borrowck/issue-41962.stderr2
-rw-r--r--src/test/ui/borrowck/issue-83760.stderr4
-rw-r--r--src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr2
-rw-r--r--src/test/ui/borrowck/move-in-pattern-mut.stderr4
-rw-r--r--src/test/ui/borrowck/move-in-pattern.stderr4
-rw-r--r--src/test/ui/borrowck/mut-borrow-in-loop-2.stderr8
-rw-r--r--src/test/ui/borrowck/or-patterns.stderr16
-rw-r--r--src/test/ui/chalkify/bugs/async.stderr39
-rw-r--r--src/test/ui/check-cfg/well-known-values.stderr2
-rw-r--r--src/test/ui/codemap_tests/tab_3.stderr4
-rw-r--r--src/test/ui/coherence/coherence-with-closure.rs1
-rw-r--r--src/test/ui/coherence/coherence-with-closure.stderr17
-rw-r--r--src/test/ui/coherence/coherence-with-generator.rs1
-rw-r--r--src/test/ui/coherence/coherence-with-generator.stderr17
-rw-r--r--src/test/ui/const-generics/projection-as-arg-const.rs20
-rw-r--r--src/test/ui/const-generics/projection-as-arg-const.stderr11
-rw-r--r--src/test/ui/consts/const-eval/infinite_loop.rs2
-rw-r--r--src/test/ui/consts/const-eval/infinite_loop.stderr6
-rw-r--r--src/test/ui/consts/issue-104768.rs4
-rw-r--r--src/test/ui/consts/issue-104768.stderr12
-rw-r--r--src/test/ui/drop/repeat-drop-2.stderr5
-rw-r--r--src/test/ui/dyn-star/dispatch-on-pin-mut.rs52
-rw-r--r--src/test/ui/dyn-star/dispatch-on-pin-mut.run.stdout1
-rw-r--r--src/test/ui/dyn-star/dispatch-on-pin-mut.stderr11
-rw-r--r--src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.rs5
-rw-r--r--src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.run.stdout2
-rw-r--r--src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr11
-rw-r--r--src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.rs13
-rw-r--r--src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr23
-rw-r--r--src/test/ui/dyn-star/upcast.rs3
-rw-r--r--src/test/ui/dyn-star/upcast.stderr20
-rw-r--r--src/test/ui/empty/empty-struct-braces-expr.rs2
-rw-r--r--src/test/ui/empty/empty-struct-braces-expr.stderr32
-rw-r--r--src/test/ui/empty/empty-struct-braces-pat-1.stderr29
-rw-r--r--src/test/ui/empty/empty-struct-braces-pat-3.stderr58
-rw-r--r--src/test/ui/error-codes/E0164.stderr2
-rw-r--r--src/test/ui/errors/issue-104621-extern-bad-file.rs8
-rw-r--r--src/test/ui/errors/issue-104621-extern-bad-file.stderr21
-rw-r--r--src/test/ui/errors/issue-104621-extern-not-file.rs4
-rw-r--r--src/test/ui/errors/issue-104621-extern-not-file.stderr8
-rw-r--r--src/test/ui/impl-trait/auto-trait.rs1
-rw-r--r--src/test/ui/impl-trait/auto-trait.stderr14
-rw-r--r--src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs17
-rw-r--r--src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr12
-rw-r--r--src/test/ui/impl-trait/negative-reasoning.rs1
-rw-r--r--src/test/ui/impl-trait/negative-reasoning.stderr14
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs2
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr19
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs5
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr49
-rw-r--r--src/test/ui/issues/issue-19086.rs2
-rw-r--r--src/test/ui/issues/issue-19086.stderr2
-rw-r--r--src/test/ui/issues/issue-23122-2.rs1
-rw-r--r--src/test/ui/issues/issue-23122-2.stderr10
-rw-r--r--src/test/ui/issues/issue-28992-empty.stderr2
-rw-r--r--src/test/ui/issues/issue-29723.stderr5
-rw-r--r--src/test/ui/issues/issue-42796.stderr4
-rw-r--r--src/test/ui/issues/issue-56835.stderr2
-rw-r--r--src/test/ui/issues/issue-63983.stderr10
-rw-r--r--src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr20
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs2
-rw-r--r--src/test/ui/lint/unused/issue-104397.rs18
-rw-r--r--src/test/ui/lint/unused/must-use-ops.rs20
-rw-r--r--src/test/ui/lint/unused/must-use-ops.stderr42
-rw-r--r--src/test/ui/lint/unused/must_use-array.rs7
-rw-r--r--src/test/ui/lint/unused/must_use-array.stderr20
-rw-r--r--src/test/ui/liveness/liveness-move-call-arg.stderr16
-rw-r--r--src/test/ui/liveness/liveness-move-in-loop.stderr14
-rw-r--r--src/test/ui/liveness/liveness-move-in-while.stderr12
-rw-r--r--src/test/ui/liveness/liveness-use-after-move.stderr4
-rw-r--r--src/test/ui/liveness/liveness-use-after-send.stderr9
-rw-r--r--src/test/ui/methods/method-path-in-pattern.stderr12
-rw-r--r--src/test/ui/mismatched_types/overloaded-calls-bad.rs19
-rw-r--r--src/test/ui/mismatched_types/overloaded-calls-bad.stderr22
-rw-r--r--src/test/ui/moves/borrow-closures-instead-of-move.stderr15
-rw-r--r--src/test/ui/moves/issue-46099-move-in-macro.stderr5
-rw-r--r--src/test/ui/moves/issue-72649-uninit-in-loop.rs6
-rw-r--r--src/test/ui/moves/issue-72649-uninit-in-loop.stderr10
-rw-r--r--src/test/ui/moves/move-fn-self-receiver.stderr10
-rw-r--r--src/test/ui/moves/move-guard-same-consts.stderr12
-rw-r--r--src/test/ui/moves/move-in-guard-1.stderr12
-rw-r--r--src/test/ui/moves/move-in-guard-2.stderr12
-rw-r--r--src/test/ui/moves/moves-based-on-type-access-to-field.stderr4
-rw-r--r--src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr2
-rw-r--r--src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr10
-rw-r--r--src/test/ui/moves/moves-based-on-type-exprs.stderr60
-rw-r--r--src/test/ui/moves/moves-based-on-type-match-bindings.stderr4
-rw-r--r--src/test/ui/moves/moves-based-on-type-tuple.stderr5
-rw-r--r--src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr5
-rw-r--r--src/test/ui/namespace/namespace-mix.rs4
-rw-r--r--src/test/ui/namespace/namespace-mix.stderr20
-rw-r--r--src/test/ui/nll/closure-access-spans.stderr10
-rw-r--r--src/test/ui/nll/issue-21232-partial-init-and-use.stderr24
-rw-r--r--src/test/ui/nll/issue-51512.stderr5
-rw-r--r--src/test/ui/nll/issue-53807.stderr2
-rw-r--r--src/test/ui/nll/match-cfg-fake-edges.stderr5
-rw-r--r--src/test/ui/nll/ref-suggestion.stderr12
-rw-r--r--src/test/ui/parser/issue-104620.rs4
-rw-r--r--src/test/ui/parser/issue-104620.stderr8
-rw-r--r--src/test/ui/parser/recover-from-bad-variant.stderr11
-rw-r--r--src/test/ui/parser/struct-literal-variant-in-if.stderr9
-rw-r--r--src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr14
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr31
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr4
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr5
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr148
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr25
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr20
-rw-r--r--src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr4
-rw-r--r--src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr10
-rw-r--r--src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr4
-rw-r--r--src/test/ui/pattern/pattern-binding-disambiguation.rs4
-rw-r--r--src/test/ui/pattern/pattern-binding-disambiguation.stderr20
-rw-r--r--src/test/ui/privacy/effective_visibilities.rs6
-rw-r--r--src/test/ui/privacy/effective_visibilities.stderr6
-rw-r--r--src/test/ui/privacy/effective_visibilities_invariants.rs12
-rw-r--r--src/test/ui/privacy/effective_visibilities_invariants.stderr32
-rw-r--r--src/test/ui/qualified/qualified-path-params.stderr2
-rw-r--r--src/test/ui/recursion/issue-83150.stderr4
-rw-r--r--src/test/ui/recursion/issue-95134.rs4
-rw-r--r--src/test/ui/recursion/issue-95134.stderr7
-rw-r--r--src/test/ui/resolve/issue-18252.rs2
-rw-r--r--src/test/ui/resolve/issue-18252.stderr9
-rw-r--r--src/test/ui/resolve/issue-19452.stderr18
-rw-r--r--src/test/ui/resolve/issue-73427.stderr22
-rw-r--r--src/test/ui/resolve/privacy-enum-ctor.stderr90
-rw-r--r--src/test/ui/rfc-2294-if-let-guard/run-pass.rs7
-rw-r--r--src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr6
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/issue-99938.rs31
-rw-r--r--src/test/ui/stats/hir-stats.rs1
-rw-r--r--src/test/ui/stats/hir-stats.stderr20
-rw-r--r--src/test/ui/structs-enums/type-sizes.rs21
-rw-r--r--src/test/ui/suggestions/borrow-for-loop-head.stderr1
-rw-r--r--src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr23
-rw-r--r--src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr28
-rw-r--r--src/test/ui/suggestions/issue-84700.stderr10
-rw-r--r--src/test/ui/suggestions/ref-pattern-binding.fixed19
-rw-r--r--src/test/ui/suggestions/ref-pattern-binding.rs19
-rw-r--r--src/test/ui/suggestions/ref-pattern-binding.stderr107
-rw-r--r--src/test/ui/threads-sendsync/mpsc_stress.rs67
-rw-r--r--src/test/ui/track-diagnostics/track2.stderr5
-rw-r--r--src/test/ui/traits/alias/issue-83613.rs1
-rw-r--r--src/test/ui/traits/alias/issue-83613.stderr14
-rw-r--r--src/test/ui/traits/predicate_can_apply-hang.rs6
-rw-r--r--src/test/ui/traits/predicate_can_apply-hang.stderr21
-rw-r--r--src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs6
-rw-r--r--src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr11
-rw-r--r--src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr4
-rw-r--r--src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr2
-rw-r--r--src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs2
-rw-r--r--src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr10
-rw-r--r--src/test/ui/type-alias-impl-trait/coherence.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/coherence.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/coherence_generalization.rs13
-rw-r--r--src/test/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs23
-rw-r--r--src/test/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs33
-rw-r--r--src/test/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr30
-rw-r--r--src/test/ui/type-alias-impl-trait/impl_trait_for_tait.rs21
-rw-r--r--src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs19
-rw-r--r--src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs16
-rw-r--r--src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-65384.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-65384.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs9
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr10
-rw-r--r--src/test/ui/typeck/hang-in-overflow.rs19
-rw-r--r--src/test/ui/typeck/hang-in-overflow.stderr22
-rw-r--r--src/test/ui/typeck/issue-104513-ice.rs6
-rw-r--r--src/test/ui/typeck/issue-104513-ice.stderr18
-rw-r--r--src/test/ui/union/union-move.mirunsafeck.stderr16
-rw-r--r--src/test/ui/union/union-move.thirunsafeck.stderr16
-rw-r--r--src/test/ui/unop-move-semantics.stderr4
-rw-r--r--src/test/ui/unsized-locals/borrow-after-move.stderr13
-rw-r--r--src/test/ui/unsized-locals/double-move.stderr8
-rw-r--r--src/test/ui/use/use-after-move-based-on-type.stderr4
-rw-r--r--src/test/ui/use/use-after-move-implicity-coerced-object.stderr8
-rw-r--r--src/tools/build-manifest/src/versions.rs4
-rw-r--r--src/tools/bump-stage0/src/main.rs2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/CHANGELOG.md159
-rw-r--r--src/tools/clippy/CODE_OF_CONDUCT.md69
-rw-r--r--src/tools/clippy/CONTRIBUTING.md33
-rw-r--r--src/tools/clippy/Cargo.toml2
-rw-r--r--src/tools/clippy/README.md8
-rw-r--r--src/tools/clippy/clippy_dev/Cargo.toml1
-rw-r--r--src/tools/clippy/clippy_dev/src/lint.rs8
-rw-r--r--src/tools/clippy/clippy_dev/src/update_lints.rs307
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml3
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/await_holding_invalid.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/cognitive_complexity.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs628
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs128
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_macros.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_methods.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_types.rs40
-rw-r--r--src/tools/clippy/clippy_lints/src/doc.rs127
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_variants.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/equatable_if_let.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/excessive_bools.rs129
-rw-r--r--src/tools/clippy/clippy_lints/src/fallible_impl_from.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs77
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/result.rs68
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_hasher.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/indexing_slicing.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/instant_subtraction.rs184
-rw-r--r--src/tools/clippy/clippy_lints/src/int_plus_one.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_enum_variant.rs60
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/let_underscore.rs157
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_all.rs368
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_cargo.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_complexity.rs111
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_correctness.rs78
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_internal.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_lints.rs620
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_nursery.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs104
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_perf.rs34
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_restriction.rs90
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_style.rs131
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs268
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs131
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs114
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_instant_elapsed.rs69
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs158
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_let_else.rs297
-rw-r--r--src/tools/clippy/clippy_lints/src/map_unit_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/infallible_destructuring_match.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_filter.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/single_match.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_last_cmp.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_next_cmp.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/expect_used.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_clone.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs281
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs (renamed from src/tools/clippy/clippy_lints/src/loops/needless_collect.rs)223
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs57
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs48
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs45
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_key.rs155
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_mut.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs108
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_continue.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/octal_escapes.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs110
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/op_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/partialeq_to_none.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_closure_call.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/renamed_lints.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/single_component_path_imports.rs219
-rw-r--r--src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs53
-rw-r--r--src/tools/clippy/clippy_lints/src/swap.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/trailing_empty_array.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs164
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/utils.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/types/box_collection.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/types/vec_box.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs40
-rw-r--r--src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_peekable.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_rounding.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_unit.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs49
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs17
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs22
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs32
-rw-r--r--src/tools/clippy/clippy_utils/src/diagnostics.rs12
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs33
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs315
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs7
-rw-r--r--src/tools/clippy/clippy_utils/src/source.rs22
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs243
-rw-r--r--src/tools/clippy/clippy_utils/src/usage.rs7
-rw-r--r--src/tools/clippy/declare_clippy_lint/Cargo.toml16
-rw-r--r--src/tools/clippy/declare_clippy_lint/src/lib.rs175
-rw-r--r--src/tools/clippy/lintcheck/src/main.rs47
-rw-r--r--src/tools/clippy/rust-toolchain4
-rw-r--r--src/tools/clippy/src/docs.rs606
-rw-r--r--src/tools/clippy/src/docs/absurd_extreme_comparisons.txt25
-rw-r--r--src/tools/clippy/src/docs/alloc_instead_of_core.txt18
-rw-r--r--src/tools/clippy/src/docs/allow_attributes_without_reason.txt22
-rw-r--r--src/tools/clippy/src/docs/almost_complete_letter_range.txt15
-rw-r--r--src/tools/clippy/src/docs/almost_swapped.txt15
-rw-r--r--src/tools/clippy/src/docs/approx_constant.txt24
-rw-r--r--src/tools/clippy/src/docs/arithmetic_side_effects.txt33
-rw-r--r--src/tools/clippy/src/docs/as_conversions.txt32
-rw-r--r--src/tools/clippy/src/docs/as_ptr_cast_mut.txt19
-rw-r--r--src/tools/clippy/src/docs/as_underscore.txt21
-rw-r--r--src/tools/clippy/src/docs/assertions_on_constants.txt14
-rw-r--r--src/tools/clippy/src/docs/assertions_on_result_states.txt14
-rw-r--r--src/tools/clippy/src/docs/assign_op_pattern.txt28
-rw-r--r--src/tools/clippy/src/docs/async_yields_async.txt28
-rw-r--r--src/tools/clippy/src/docs/await_holding_invalid_type.txt29
-rw-r--r--src/tools/clippy/src/docs/await_holding_lock.txt51
-rw-r--r--src/tools/clippy/src/docs/await_holding_refcell_ref.txt47
-rw-r--r--src/tools/clippy/src/docs/bad_bit_mask.txt30
-rw-r--r--src/tools/clippy/src/docs/bind_instead_of_map.txt22
-rw-r--r--src/tools/clippy/src/docs/blanket_clippy_restriction_lints.txt16
-rw-r--r--src/tools/clippy/src/docs/blocks_in_if_conditions.txt21
-rw-r--r--src/tools/clippy/src/docs/bool_assert_comparison.txt16
-rw-r--r--src/tools/clippy/src/docs/bool_comparison.txt18
-rw-r--r--src/tools/clippy/src/docs/bool_to_int_with_if.txt26
-rw-r--r--src/tools/clippy/src/docs/borrow_as_ptr.txt26
-rw-r--r--src/tools/clippy/src/docs/borrow_deref_ref.txt27
-rw-r--r--src/tools/clippy/src/docs/borrow_interior_mutable_const.txt40
-rw-r--r--src/tools/clippy/src/docs/borrowed_box.txt19
-rw-r--r--src/tools/clippy/src/docs/box_collection.txt23
-rw-r--r--src/tools/clippy/src/docs/box_default.txt17
-rw-r--r--src/tools/clippy/src/docs/boxed_local.txt18
-rw-r--r--src/tools/clippy/src/docs/branches_sharing_code.txt32
-rw-r--r--src/tools/clippy/src/docs/builtin_type_shadow.txt15
-rw-r--r--src/tools/clippy/src/docs/bytes_count_to_len.txt18
-rw-r--r--src/tools/clippy/src/docs/bytes_nth.txt16
-rw-r--r--src/tools/clippy/src/docs/cargo_common_metadata.txt33
-rw-r--r--src/tools/clippy/src/docs/case_sensitive_file_extension_comparisons.txt21
-rw-r--r--src/tools/clippy/src/docs/cast_abs_to_unsigned.txt16
-rw-r--r--src/tools/clippy/src/docs/cast_enum_constructor.txt11
-rw-r--r--src/tools/clippy/src/docs/cast_enum_truncation.txt12
-rw-r--r--src/tools/clippy/src/docs/cast_lossless.txt26
-rw-r--r--src/tools/clippy/src/docs/cast_nan_to_int.txt15
-rw-r--r--src/tools/clippy/src/docs/cast_possible_truncation.txt16
-rw-r--r--src/tools/clippy/src/docs/cast_possible_wrap.txt17
-rw-r--r--src/tools/clippy/src/docs/cast_precision_loss.txt19
-rw-r--r--src/tools/clippy/src/docs/cast_ptr_alignment.txt21
-rw-r--r--src/tools/clippy/src/docs/cast_ref_to_mut.txt28
-rw-r--r--src/tools/clippy/src/docs/cast_sign_loss.txt15
-rw-r--r--src/tools/clippy/src/docs/cast_slice_different_sizes.txt38
-rw-r--r--src/tools/clippy/src/docs/cast_slice_from_raw_parts.txt20
-rw-r--r--src/tools/clippy/src/docs/char_lit_as_u8.txt21
-rw-r--r--src/tools/clippy/src/docs/chars_last_cmp.txt17
-rw-r--r--src/tools/clippy/src/docs/chars_next_cmp.txt19
-rw-r--r--src/tools/clippy/src/docs/checked_conversions.txt15
-rw-r--r--src/tools/clippy/src/docs/clone_double_ref.txt16
-rw-r--r--src/tools/clippy/src/docs/clone_on_copy.txt11
-rw-r--r--src/tools/clippy/src/docs/clone_on_ref_ptr.txt21
-rw-r--r--src/tools/clippy/src/docs/cloned_instead_of_copied.txt16
-rw-r--r--src/tools/clippy/src/docs/cmp_nan.txt16
-rw-r--r--src/tools/clippy/src/docs/cmp_null.txt23
-rw-r--r--src/tools/clippy/src/docs/cmp_owned.txt18
-rw-r--r--src/tools/clippy/src/docs/cognitive_complexity.txt13
-rw-r--r--src/tools/clippy/src/docs/collapsible_else_if.txt29
-rw-r--r--src/tools/clippy/src/docs/collapsible_if.txt23
-rw-r--r--src/tools/clippy/src/docs/collapsible_match.txt31
-rw-r--r--src/tools/clippy/src/docs/collapsible_str_replace.txt19
-rw-r--r--src/tools/clippy/src/docs/comparison_chain.txt36
-rw-r--r--src/tools/clippy/src/docs/comparison_to_empty.txt31
-rw-r--r--src/tools/clippy/src/docs/copy_iterator.txt20
-rw-r--r--src/tools/clippy/src/docs/crate_in_macro_def.txt35
-rw-r--r--src/tools/clippy/src/docs/create_dir.txt15
-rw-r--r--src/tools/clippy/src/docs/crosspointer_transmute.txt12
-rw-r--r--src/tools/clippy/src/docs/dbg_macro.txt16
-rw-r--r--src/tools/clippy/src/docs/debug_assert_with_mut_call.txt18
-rw-r--r--src/tools/clippy/src/docs/decimal_literal_representation.txt13
-rw-r--r--src/tools/clippy/src/docs/declare_interior_mutable_const.txt46
-rw-r--r--src/tools/clippy/src/docs/default_instead_of_iter_empty.txt15
-rw-r--r--src/tools/clippy/src/docs/default_numeric_fallback.txt28
-rw-r--r--src/tools/clippy/src/docs/default_trait_access.txt16
-rw-r--r--src/tools/clippy/src/docs/default_union_representation.txt36
-rw-r--r--src/tools/clippy/src/docs/deprecated_cfg_attr.txt24
-rw-r--r--src/tools/clippy/src/docs/deprecated_semver.txt13
-rw-r--r--src/tools/clippy/src/docs/deref_addrof.txt22
-rw-r--r--src/tools/clippy/src/docs/deref_by_slicing.txt17
-rw-r--r--src/tools/clippy/src/docs/derivable_impls.txt35
-rw-r--r--src/tools/clippy/src/docs/derive_hash_xor_eq.txt23
-rw-r--r--src/tools/clippy/src/docs/derive_ord_xor_partial_ord.txt44
-rw-r--r--src/tools/clippy/src/docs/derive_partial_eq_without_eq.txt25
-rw-r--r--src/tools/clippy/src/docs/disallowed_macros.txt36
-rw-r--r--src/tools/clippy/src/docs/disallowed_methods.txt41
-rw-r--r--src/tools/clippy/src/docs/disallowed_names.txt12
-rw-r--r--src/tools/clippy/src/docs/disallowed_script_idents.txt32
-rw-r--r--src/tools/clippy/src/docs/disallowed_types.txt33
-rw-r--r--src/tools/clippy/src/docs/diverging_sub_expression.txt19
-rw-r--r--src/tools/clippy/src/docs/doc_link_with_quotes.txt16
-rw-r--r--src/tools/clippy/src/docs/doc_markdown.txt35
-rw-r--r--src/tools/clippy/src/docs/double_comparisons.txt17
-rw-r--r--src/tools/clippy/src/docs/double_must_use.txt17
-rw-r--r--src/tools/clippy/src/docs/double_neg.txt12
-rw-r--r--src/tools/clippy/src/docs/double_parens.txt24
-rw-r--r--src/tools/clippy/src/docs/drop_copy.txt15
-rw-r--r--src/tools/clippy/src/docs/drop_non_drop.txt13
-rw-r--r--src/tools/clippy/src/docs/drop_ref.txt17
-rw-r--r--src/tools/clippy/src/docs/duplicate_mod.txt31
-rw-r--r--src/tools/clippy/src/docs/duplicate_underscore_argument.txt16
-rw-r--r--src/tools/clippy/src/docs/duration_subsec.txt19
-rw-r--r--src/tools/clippy/src/docs/else_if_without_else.txt27
-rw-r--r--src/tools/clippy/src/docs/empty_drop.txt20
-rw-r--r--src/tools/clippy/src/docs/empty_enum.txt27
-rw-r--r--src/tools/clippy/src/docs/empty_line_after_outer_attr.txt35
-rw-r--r--src/tools/clippy/src/docs/empty_loop.txt27
-rw-r--r--src/tools/clippy/src/docs/empty_structs_with_brackets.txt14
-rw-r--r--src/tools/clippy/src/docs/enum_clike_unportable_variant.txt16
-rw-r--r--src/tools/clippy/src/docs/enum_glob_use.txt24
-rw-r--r--src/tools/clippy/src/docs/enum_variant_names.txt30
-rw-r--r--src/tools/clippy/src/docs/eq_op.txt22
-rw-r--r--src/tools/clippy/src/docs/equatable_if_let.txt23
-rw-r--r--src/tools/clippy/src/docs/erasing_op.txt15
-rw-r--r--src/tools/clippy/src/docs/err_expect.txt16
-rw-r--r--src/tools/clippy/src/docs/excessive_precision.txt18
-rw-r--r--src/tools/clippy/src/docs/exhaustive_enums.txt23
-rw-r--r--src/tools/clippy/src/docs/exhaustive_structs.txt23
-rw-r--r--src/tools/clippy/src/docs/exit.txt12
-rw-r--r--src/tools/clippy/src/docs/expect_fun_call.txt24
-rw-r--r--src/tools/clippy/src/docs/expect_used.txt26
-rw-r--r--src/tools/clippy/src/docs/expl_impl_clone_on_copy.txt20
-rw-r--r--src/tools/clippy/src/docs/explicit_auto_deref.txt16
-rw-r--r--src/tools/clippy/src/docs/explicit_counter_loop.txt21
-rw-r--r--src/tools/clippy/src/docs/explicit_deref_methods.txt24
-rw-r--r--src/tools/clippy/src/docs/explicit_into_iter_loop.txt20
-rw-r--r--src/tools/clippy/src/docs/explicit_iter_loop.txt25
-rw-r--r--src/tools/clippy/src/docs/explicit_write.txt18
-rw-r--r--src/tools/clippy/src/docs/extend_with_drain.txt21
-rw-r--r--src/tools/clippy/src/docs/extra_unused_lifetimes.txt23
-rw-r--r--src/tools/clippy/src/docs/fallible_impl_from.txt32
-rw-r--r--src/tools/clippy/src/docs/field_reassign_with_default.txt23
-rw-r--r--src/tools/clippy/src/docs/filetype_is_file.txt29
-rw-r--r--src/tools/clippy/src/docs/filter_map_identity.txt14
-rw-r--r--src/tools/clippy/src/docs/filter_map_next.txt16
-rw-r--r--src/tools/clippy/src/docs/filter_next.txt16
-rw-r--r--src/tools/clippy/src/docs/flat_map_identity.txt14
-rw-r--r--src/tools/clippy/src/docs/flat_map_option.txt16
-rw-r--r--src/tools/clippy/src/docs/float_arithmetic.txt11
-rw-r--r--src/tools/clippy/src/docs/float_cmp.txt28
-rw-r--r--src/tools/clippy/src/docs/float_cmp_const.txt26
-rw-r--r--src/tools/clippy/src/docs/float_equality_without_abs.txt26
-rw-r--r--src/tools/clippy/src/docs/fn_address_comparisons.txt17
-rw-r--r--src/tools/clippy/src/docs/fn_params_excessive_bools.txt31
-rw-r--r--src/tools/clippy/src/docs/fn_to_numeric_cast.txt21
-rw-r--r--src/tools/clippy/src/docs/fn_to_numeric_cast_any.txt35
-rw-r--r--src/tools/clippy/src/docs/fn_to_numeric_cast_with_truncation.txt26
-rw-r--r--src/tools/clippy/src/docs/for_kv_map.txt22
-rw-r--r--src/tools/clippy/src/docs/forget_copy.txt21
-rw-r--r--src/tools/clippy/src/docs/forget_non_drop.txt13
-rw-r--r--src/tools/clippy/src/docs/forget_ref.txt15
-rw-r--r--src/tools/clippy/src/docs/format_in_format_args.txt16
-rw-r--r--src/tools/clippy/src/docs/format_push_string.txt26
-rw-r--r--src/tools/clippy/src/docs/from_iter_instead_of_collect.txt24
-rw-r--r--src/tools/clippy/src/docs/from_over_into.txt26
-rw-r--r--src/tools/clippy/src/docs/from_str_radix_10.txt25
-rw-r--r--src/tools/clippy/src/docs/future_not_send.txt29
-rw-r--r--src/tools/clippy/src/docs/get_first.txt19
-rw-r--r--src/tools/clippy/src/docs/get_last_with_len.txt26
-rw-r--r--src/tools/clippy/src/docs/get_unwrap.txt30
-rw-r--r--src/tools/clippy/src/docs/identity_op.txt11
-rw-r--r--src/tools/clippy/src/docs/if_let_mutex.txt25
-rw-r--r--src/tools/clippy/src/docs/if_not_else.txt25
-rw-r--r--src/tools/clippy/src/docs/if_same_then_else.txt15
-rw-r--r--src/tools/clippy/src/docs/if_then_some_else_none.txt26
-rw-r--r--src/tools/clippy/src/docs/ifs_same_cond.txt25
-rw-r--r--src/tools/clippy/src/docs/implicit_clone.txt19
-rw-r--r--src/tools/clippy/src/docs/implicit_hasher.txt26
-rw-r--r--src/tools/clippy/src/docs/implicit_return.txt22
-rw-r--r--src/tools/clippy/src/docs/implicit_saturating_add.txt20
-rw-r--r--src/tools/clippy/src/docs/implicit_saturating_sub.txt21
-rw-r--r--src/tools/clippy/src/docs/imprecise_flops.txt23
-rw-r--r--src/tools/clippy/src/docs/inconsistent_digit_grouping.txt17
-rw-r--r--src/tools/clippy/src/docs/inconsistent_struct_constructor.txt40
-rw-r--r--src/tools/clippy/src/docs/index_refutable_slice.txt29
-rw-r--r--src/tools/clippy/src/docs/indexing_slicing.txt33
-rw-r--r--src/tools/clippy/src/docs/ineffective_bit_mask.txt25
-rw-r--r--src/tools/clippy/src/docs/inefficient_to_string.txt17
-rw-r--r--src/tools/clippy/src/docs/infallible_destructuring_match.txt29
-rw-r--r--src/tools/clippy/src/docs/infinite_iter.txt13
-rw-r--r--src/tools/clippy/src/docs/inherent_to_string.txt29
-rw-r--r--src/tools/clippy/src/docs/inherent_to_string_shadow_display.txt37
-rw-r--r--src/tools/clippy/src/docs/init_numbered_fields.txt24
-rw-r--r--src/tools/clippy/src/docs/inline_always.txt23
-rw-r--r--src/tools/clippy/src/docs/inline_asm_x86_att_syntax.txt16
-rw-r--r--src/tools/clippy/src/docs/inline_asm_x86_intel_syntax.txt16
-rw-r--r--src/tools/clippy/src/docs/inline_fn_without_body.txt14
-rw-r--r--src/tools/clippy/src/docs/inspect_for_each.txt23
-rw-r--r--src/tools/clippy/src/docs/int_plus_one.txt15
-rw-r--r--src/tools/clippy/src/docs/integer_arithmetic.txt18
-rw-r--r--src/tools/clippy/src/docs/integer_division.txt19
-rw-r--r--src/tools/clippy/src/docs/into_iter_on_ref.txt18
-rw-r--r--src/tools/clippy/src/docs/invalid_null_ptr_usage.txt16
-rw-r--r--src/tools/clippy/src/docs/invalid_regex.txt12
-rw-r--r--src/tools/clippy/src/docs/invalid_upcast_comparisons.txt18
-rw-r--r--src/tools/clippy/src/docs/invalid_utf8_in_unchecked.txt12
-rw-r--r--src/tools/clippy/src/docs/invisible_characters.txt10
-rw-r--r--src/tools/clippy/src/docs/is_digit_ascii_radix.txt20
-rw-r--r--src/tools/clippy/src/docs/items_after_statements.txt37
-rw-r--r--src/tools/clippy/src/docs/iter_cloned_collect.txt17
-rw-r--r--src/tools/clippy/src/docs/iter_count.txt22
-rw-r--r--src/tools/clippy/src/docs/iter_kv_map.txt22
-rw-r--r--src/tools/clippy/src/docs/iter_next_loop.txt17
-rw-r--r--src/tools/clippy/src/docs/iter_next_slice.txt16
-rw-r--r--src/tools/clippy/src/docs/iter_not_returning_iterator.txt26
-rw-r--r--src/tools/clippy/src/docs/iter_nth.txt20
-rw-r--r--src/tools/clippy/src/docs/iter_nth_zero.txt17
-rw-r--r--src/tools/clippy/src/docs/iter_on_empty_collections.txt25
-rw-r--r--src/tools/clippy/src/docs/iter_on_single_items.txt24
-rw-r--r--src/tools/clippy/src/docs/iter_overeager_cloned.txt22
-rw-r--r--src/tools/clippy/src/docs/iter_skip_next.txt18
-rw-r--r--src/tools/clippy/src/docs/iter_with_drain.txt16
-rw-r--r--src/tools/clippy/src/docs/iterator_step_by_zero.txt13
-rw-r--r--src/tools/clippy/src/docs/just_underscores_and_digits.txt14
-rw-r--r--src/tools/clippy/src/docs/large_const_arrays.txt17
-rw-r--r--src/tools/clippy/src/docs/large_digit_groups.txt12
-rw-r--r--src/tools/clippy/src/docs/large_enum_variant.txt41
-rw-r--r--src/tools/clippy/src/docs/large_include_file.txt21
-rw-r--r--src/tools/clippy/src/docs/large_stack_arrays.txt10
-rw-r--r--src/tools/clippy/src/docs/large_types_passed_by_value.txt24
-rw-r--r--src/tools/clippy/src/docs/len_without_is_empty.txt19
-rw-r--r--src/tools/clippy/src/docs/len_zero.txt28
-rw-r--r--src/tools/clippy/src/docs/let_and_return.txt21
-rw-r--r--src/tools/clippy/src/docs/let_underscore_drop.txt29
-rw-r--r--src/tools/clippy/src/docs/let_underscore_lock.txt20
-rw-r--r--src/tools/clippy/src/docs/let_underscore_must_use.txt17
-rw-r--r--src/tools/clippy/src/docs/let_unit_value.txt13
-rw-r--r--src/tools/clippy/src/docs/linkedlist.txt32
-rw-r--r--src/tools/clippy/src/docs/lossy_float_literal.txt18
-rw-r--r--src/tools/clippy/src/docs/macro_use_imports.txt12
-rw-r--r--src/tools/clippy/src/docs/main_recursion.txt13
-rw-r--r--src/tools/clippy/src/docs/manual_assert.txt18
-rw-r--r--src/tools/clippy/src/docs/manual_async_fn.txt16
-rw-r--r--src/tools/clippy/src/docs/manual_bits.txt15
-rw-r--r--src/tools/clippy/src/docs/manual_clamp.txt46
-rw-r--r--src/tools/clippy/src/docs/manual_filter.txt21
-rw-r--r--src/tools/clippy/src/docs/manual_filter_map.txt19
-rw-r--r--src/tools/clippy/src/docs/manual_find.txt24
-rw-r--r--src/tools/clippy/src/docs/manual_find_map.txt19
-rw-r--r--src/tools/clippy/src/docs/manual_flatten.txt25
-rw-r--r--src/tools/clippy/src/docs/manual_instant_elapsed.txt21
-rw-r--r--src/tools/clippy/src/docs/manual_map.txt17
-rw-r--r--src/tools/clippy/src/docs/manual_memcpy.txt18
-rw-r--r--src/tools/clippy/src/docs/manual_non_exhaustive.txt41
-rw-r--r--src/tools/clippy/src/docs/manual_ok_or.txt19
-rw-r--r--src/tools/clippy/src/docs/manual_range_contains.txt19
-rw-r--r--src/tools/clippy/src/docs/manual_rem_euclid.txt17
-rw-r--r--src/tools/clippy/src/docs/manual_retain.txt15
-rw-r--r--src/tools/clippy/src/docs/manual_saturating_arithmetic.txt18
-rw-r--r--src/tools/clippy/src/docs/manual_split_once.txt29
-rw-r--r--src/tools/clippy/src/docs/manual_str_repeat.txt15
-rw-r--r--src/tools/clippy/src/docs/manual_string_new.txt20
-rw-r--r--src/tools/clippy/src/docs/manual_strip.txt24
-rw-r--r--src/tools/clippy/src/docs/manual_swap.txt22
-rw-r--r--src/tools/clippy/src/docs/manual_unwrap_or.txt20
-rw-r--r--src/tools/clippy/src/docs/many_single_char_names.txt12
-rw-r--r--src/tools/clippy/src/docs/map_clone.txt22
-rw-r--r--src/tools/clippy/src/docs/map_collect_result_unit.txt14
-rw-r--r--src/tools/clippy/src/docs/map_entry.txt28
-rw-r--r--src/tools/clippy/src/docs/map_err_ignore.txt93
-rw-r--r--src/tools/clippy/src/docs/map_flatten.txt21
-rw-r--r--src/tools/clippy/src/docs/map_identity.txt16
-rw-r--r--src/tools/clippy/src/docs/map_unwrap_or.txt22
-rw-r--r--src/tools/clippy/src/docs/match_as_ref.txt23
-rw-r--r--src/tools/clippy/src/docs/match_bool.txt24
-rw-r--r--src/tools/clippy/src/docs/match_like_matches_macro.txt32
-rw-r--r--src/tools/clippy/src/docs/match_on_vec_items.txt29
-rw-r--r--src/tools/clippy/src/docs/match_overlapping_arm.txt16
-rw-r--r--src/tools/clippy/src/docs/match_ref_pats.txt26
-rw-r--r--src/tools/clippy/src/docs/match_result_ok.txt27
-rw-r--r--src/tools/clippy/src/docs/match_same_arms.txt38
-rw-r--r--src/tools/clippy/src/docs/match_single_binding.txt23
-rw-r--r--src/tools/clippy/src/docs/match_str_case_mismatch.txt22
-rw-r--r--src/tools/clippy/src/docs/match_wild_err_arm.txt16
-rw-r--r--src/tools/clippy/src/docs/match_wildcard_for_single_variants.txt27
-rw-r--r--src/tools/clippy/src/docs/maybe_infinite_iter.txt16
-rw-r--r--src/tools/clippy/src/docs/mem_forget.txt12
-rw-r--r--src/tools/clippy/src/docs/mem_replace_option_with_none.txt21
-rw-r--r--src/tools/clippy/src/docs/mem_replace_with_default.txt18
-rw-r--r--src/tools/clippy/src/docs/mem_replace_with_uninit.txt24
-rw-r--r--src/tools/clippy/src/docs/min_max.txt18
-rw-r--r--src/tools/clippy/src/docs/mismatched_target_os.txt24
-rw-r--r--src/tools/clippy/src/docs/mismatching_type_param_order.txt33
-rw-r--r--src/tools/clippy/src/docs/misrefactored_assign_op.txt20
-rw-r--r--src/tools/clippy/src/docs/missing_const_for_fn.txt40
-rw-r--r--src/tools/clippy/src/docs/missing_docs_in_private_items.txt9
-rw-r--r--src/tools/clippy/src/docs/missing_enforced_import_renames.txt22
-rw-r--r--src/tools/clippy/src/docs/missing_errors_doc.txt21
-rw-r--r--src/tools/clippy/src/docs/missing_inline_in_public_items.txt45
-rw-r--r--src/tools/clippy/src/docs/missing_panics_doc.txt24
-rw-r--r--src/tools/clippy/src/docs/missing_safety_doc.txt26
-rw-r--r--src/tools/clippy/src/docs/missing_spin_loop.txt27
-rw-r--r--src/tools/clippy/src/docs/missing_trait_methods.txt40
-rw-r--r--src/tools/clippy/src/docs/mistyped_literal_suffixes.txt15
-rw-r--r--src/tools/clippy/src/docs/mixed_case_hex_literals.txt16
-rw-r--r--src/tools/clippy/src/docs/mixed_read_write_in_expression.txt32
-rw-r--r--src/tools/clippy/src/docs/mod_module_files.txt22
-rw-r--r--src/tools/clippy/src/docs/module_inception.txt24
-rw-r--r--src/tools/clippy/src/docs/module_name_repetitions.txt20
-rw-r--r--src/tools/clippy/src/docs/modulo_arithmetic.txt15
-rw-r--r--src/tools/clippy/src/docs/modulo_one.txt16
-rw-r--r--src/tools/clippy/src/docs/multi_assignments.txt17
-rw-r--r--src/tools/clippy/src/docs/multiple_crate_versions.txt19
-rw-r--r--src/tools/clippy/src/docs/multiple_inherent_impl.txt26
-rw-r--r--src/tools/clippy/src/docs/must_use_candidate.txt23
-rw-r--r--src/tools/clippy/src/docs/must_use_unit.txt13
-rw-r--r--src/tools/clippy/src/docs/mut_from_ref.txt26
-rw-r--r--src/tools/clippy/src/docs/mut_mut.txt12
-rw-r--r--src/tools/clippy/src/docs/mut_mutex_lock.txt29
-rw-r--r--src/tools/clippy/src/docs/mut_range_bound.txt29
-rw-r--r--src/tools/clippy/src/docs/mutable_key_type.txt61
-rw-r--r--src/tools/clippy/src/docs/mutex_atomic.txt22
-rw-r--r--src/tools/clippy/src/docs/mutex_integer.txt22
-rw-r--r--src/tools/clippy/src/docs/naive_bytecount.txt22
-rw-r--r--src/tools/clippy/src/docs/needless_arbitrary_self_type.txt44
-rw-r--r--src/tools/clippy/src/docs/needless_bitwise_bool.txt22
-rw-r--r--src/tools/clippy/src/docs/needless_bool.txt26
-rw-r--r--src/tools/clippy/src/docs/needless_borrow.txt21
-rw-r--r--src/tools/clippy/src/docs/needless_borrowed_reference.txt22
-rw-r--r--src/tools/clippy/src/docs/needless_collect.txt14
-rw-r--r--src/tools/clippy/src/docs/needless_continue.txt61
-rw-r--r--src/tools/clippy/src/docs/needless_doctest_main.txt22
-rw-r--r--src/tools/clippy/src/docs/needless_for_each.txt24
-rw-r--r--src/tools/clippy/src/docs/needless_late_init.txt42
-rw-r--r--src/tools/clippy/src/docs/needless_lifetimes.txt29
-rw-r--r--src/tools/clippy/src/docs/needless_match.txt36
-rw-r--r--src/tools/clippy/src/docs/needless_option_as_deref.txt18
-rw-r--r--src/tools/clippy/src/docs/needless_option_take.txt17
-rw-r--r--src/tools/clippy/src/docs/needless_parens_on_range_literals.txt23
-rw-r--r--src/tools/clippy/src/docs/needless_pass_by_value.txt27
-rw-r--r--src/tools/clippy/src/docs/needless_question_mark.txt43
-rw-r--r--src/tools/clippy/src/docs/needless_range_loop.txt23
-rw-r--r--src/tools/clippy/src/docs/needless_return.txt19
-rw-r--r--src/tools/clippy/src/docs/needless_splitn.txt16
-rw-r--r--src/tools/clippy/src/docs/needless_update.txt30
-rw-r--r--src/tools/clippy/src/docs/neg_cmp_op_on_partial_ord.txt26
-rw-r--r--src/tools/clippy/src/docs/neg_multiply.txt18
-rw-r--r--src/tools/clippy/src/docs/negative_feature_names.txt22
-rw-r--r--src/tools/clippy/src/docs/never_loop.txt15
-rw-r--r--src/tools/clippy/src/docs/new_ret_no_self.txt47
-rw-r--r--src/tools/clippy/src/docs/new_without_default.txt32
-rw-r--r--src/tools/clippy/src/docs/no_effect.txt12
-rw-r--r--src/tools/clippy/src/docs/no_effect_replace.txt11
-rw-r--r--src/tools/clippy/src/docs/no_effect_underscore_binding.txt16
-rw-r--r--src/tools/clippy/src/docs/non_ascii_literal.txt19
-rw-r--r--src/tools/clippy/src/docs/non_octal_unix_permissions.txt23
-rw-r--r--src/tools/clippy/src/docs/non_send_fields_in_send_ty.txt36
-rw-r--r--src/tools/clippy/src/docs/nonminimal_bool.txt23
-rw-r--r--src/tools/clippy/src/docs/nonsensical_open_options.txt14
-rw-r--r--src/tools/clippy/src/docs/nonstandard_macro_braces.txt15
-rw-r--r--src/tools/clippy/src/docs/not_unsafe_ptr_arg_deref.txt30
-rw-r--r--src/tools/clippy/src/docs/obfuscated_if_else.txt21
-rw-r--r--src/tools/clippy/src/docs/octal_escapes.txt33
-rw-r--r--src/tools/clippy/src/docs/ok_expect.txt19
-rw-r--r--src/tools/clippy/src/docs/only_used_in_recursion.txt58
-rw-r--r--src/tools/clippy/src/docs/op_ref.txt17
-rw-r--r--src/tools/clippy/src/docs/option_as_ref_deref.txt15
-rw-r--r--src/tools/clippy/src/docs/option_env_unwrap.txt19
-rw-r--r--src/tools/clippy/src/docs/option_filter_map.txt15
-rw-r--r--src/tools/clippy/src/docs/option_if_let_else.txt46
-rw-r--r--src/tools/clippy/src/docs/option_map_or_none.txt19
-rw-r--r--src/tools/clippy/src/docs/option_map_unit_fn.txt27
-rw-r--r--src/tools/clippy/src/docs/option_option.txt32
-rw-r--r--src/tools/clippy/src/docs/or_fun_call.txt27
-rw-r--r--src/tools/clippy/src/docs/or_then_unwrap.txt22
-rw-r--r--src/tools/clippy/src/docs/out_of_bounds_indexing.txt22
-rw-r--r--src/tools/clippy/src/docs/overflow_check_conditional.txt11
-rw-r--r--src/tools/clippy/src/docs/overly_complex_bool_expr.txt20
-rw-r--r--src/tools/clippy/src/docs/panic.txt10
-rw-r--r--src/tools/clippy/src/docs/panic_in_result_fn.txt22
-rw-r--r--src/tools/clippy/src/docs/panicking_unwrap.txt18
-rw-r--r--src/tools/clippy/src/docs/partial_pub_fields.txt27
-rw-r--r--src/tools/clippy/src/docs/partialeq_ne_impl.txt18
-rw-r--r--src/tools/clippy/src/docs/partialeq_to_none.txt24
-rw-r--r--src/tools/clippy/src/docs/path_buf_push_overwrite.txt25
-rw-r--r--src/tools/clippy/src/docs/pattern_type_mismatch.txt64
-rw-r--r--src/tools/clippy/src/docs/possible_missing_comma.txt14
-rw-r--r--src/tools/clippy/src/docs/precedence.txt17
-rw-r--r--src/tools/clippy/src/docs/print_in_format_impl.txt34
-rw-r--r--src/tools/clippy/src/docs/print_literal.txt16
-rw-r--r--src/tools/clippy/src/docs/print_stderr.txt15
-rw-r--r--src/tools/clippy/src/docs/print_stdout.txt15
-rw-r--r--src/tools/clippy/src/docs/print_with_newline.txt16
-rw-r--r--src/tools/clippy/src/docs/println_empty_string.txt16
-rw-r--r--src/tools/clippy/src/docs/ptr_arg.txt29
-rw-r--r--src/tools/clippy/src/docs/ptr_as_ptr.txt22
-rw-r--r--src/tools/clippy/src/docs/ptr_eq.txt22
-rw-r--r--src/tools/clippy/src/docs/ptr_offset_with_cast.txt30
-rw-r--r--src/tools/clippy/src/docs/pub_use.txt28
-rw-r--r--src/tools/clippy/src/docs/question_mark.txt18
-rw-r--r--src/tools/clippy/src/docs/range_minus_one.txt27
-rw-r--r--src/tools/clippy/src/docs/range_plus_one.txt36
-rw-r--r--src/tools/clippy/src/docs/range_zip_with_len.txt16
-rw-r--r--src/tools/clippy/src/docs/rc_buffer.txt27
-rw-r--r--src/tools/clippy/src/docs/rc_clone_in_vec_init.txt29
-rw-r--r--src/tools/clippy/src/docs/rc_mutex.txt26
-rw-r--r--src/tools/clippy/src/docs/read_zero_byte_vec.txt30
-rw-r--r--src/tools/clippy/src/docs/recursive_format_impl.txt32
-rw-r--r--src/tools/clippy/src/docs/redundant_allocation.txt17
-rw-r--r--src/tools/clippy/src/docs/redundant_clone.txt23
-rw-r--r--src/tools/clippy/src/docs/redundant_closure.txt25
-rw-r--r--src/tools/clippy/src/docs/redundant_closure_call.txt17
-rw-r--r--src/tools/clippy/src/docs/redundant_closure_for_method_calls.txt15
-rw-r--r--src/tools/clippy/src/docs/redundant_else.txt30
-rw-r--r--src/tools/clippy/src/docs/redundant_feature_names.txt23
-rw-r--r--src/tools/clippy/src/docs/redundant_field_names.txt22
-rw-r--r--src/tools/clippy/src/docs/redundant_pattern.txt22
-rw-r--r--src/tools/clippy/src/docs/redundant_pattern_matching.txt45
-rw-r--r--src/tools/clippy/src/docs/redundant_pub_crate.txt21
-rw-r--r--src/tools/clippy/src/docs/redundant_slicing.txt24
-rw-r--r--src/tools/clippy/src/docs/redundant_static_lifetimes.txt19
-rw-r--r--src/tools/clippy/src/docs/ref_binding_to_reference.txt21
-rw-r--r--src/tools/clippy/src/docs/ref_option_ref.txt19
-rw-r--r--src/tools/clippy/src/docs/repeat_once.txt25
-rw-r--r--src/tools/clippy/src/docs/rest_pat_in_fully_bound_structs.txt24
-rw-r--r--src/tools/clippy/src/docs/result_large_err.txt36
-rw-r--r--src/tools/clippy/src/docs/result_map_or_into_option.txt16
-rw-r--r--src/tools/clippy/src/docs/result_map_unit_fn.txt26
-rw-r--r--src/tools/clippy/src/docs/result_unit_err.txt40
-rw-r--r--src/tools/clippy/src/docs/return_self_not_must_use.txt46
-rw-r--r--src/tools/clippy/src/docs/reversed_empty_ranges.txt26
-rw-r--r--src/tools/clippy/src/docs/same_functions_in_if_condition.txt41
-rw-r--r--src/tools/clippy/src/docs/same_item_push.txt29
-rw-r--r--src/tools/clippy/src/docs/same_name_method.txt23
-rw-r--r--src/tools/clippy/src/docs/search_is_some.txt24
-rw-r--r--src/tools/clippy/src/docs/self_assignment.txt32
-rw-r--r--src/tools/clippy/src/docs/self_named_constructors.txt26
-rw-r--r--src/tools/clippy/src/docs/self_named_module_files.txt22
-rw-r--r--src/tools/clippy/src/docs/semicolon_if_nothing_returned.txt20
-rw-r--r--src/tools/clippy/src/docs/separated_literal_suffix.txt17
-rw-r--r--src/tools/clippy/src/docs/serde_api_misuse.txt10
-rw-r--r--src/tools/clippy/src/docs/shadow_reuse.txt20
-rw-r--r--src/tools/clippy/src/docs/shadow_same.txt18
-rw-r--r--src/tools/clippy/src/docs/shadow_unrelated.txt22
-rw-r--r--src/tools/clippy/src/docs/short_circuit_statement.txt14
-rw-r--r--src/tools/clippy/src/docs/should_implement_trait.txt22
-rw-r--r--src/tools/clippy/src/docs/significant_drop_in_scrutinee.txt43
-rw-r--r--src/tools/clippy/src/docs/similar_names.txt16
-rw-r--r--src/tools/clippy/src/docs/single_char_add_str.txt18
-rw-r--r--src/tools/clippy/src/docs/single_char_lifetime_names.txt28
-rw-r--r--src/tools/clippy/src/docs/single_char_pattern.txt20
-rw-r--r--src/tools/clippy/src/docs/single_component_path_imports.txt21
-rw-r--r--src/tools/clippy/src/docs/single_element_loop.txt21
-rw-r--r--src/tools/clippy/src/docs/single_match.txt21
-rw-r--r--src/tools/clippy/src/docs/single_match_else.txt29
-rw-r--r--src/tools/clippy/src/docs/size_of_in_element_count.txt16
-rw-r--r--src/tools/clippy/src/docs/skip_while_next.txt16
-rw-r--r--src/tools/clippy/src/docs/slow_vector_initialization.txt24
-rw-r--r--src/tools/clippy/src/docs/stable_sort_primitive.txt31
-rw-r--r--src/tools/clippy/src/docs/std_instead_of_alloc.txt18
-rw-r--r--src/tools/clippy/src/docs/std_instead_of_core.txt18
-rw-r--r--src/tools/clippy/src/docs/str_to_string.txt18
-rw-r--r--src/tools/clippy/src/docs/string_add.txt27
-rw-r--r--src/tools/clippy/src/docs/string_add_assign.txt17
-rw-r--r--src/tools/clippy/src/docs/string_extend_chars.txt23
-rw-r--r--src/tools/clippy/src/docs/string_from_utf8_as_bytes.txt15
-rw-r--r--src/tools/clippy/src/docs/string_lit_as_bytes.txt39
-rw-r--r--src/tools/clippy/src/docs/string_slice.txt17
-rw-r--r--src/tools/clippy/src/docs/string_to_string.txt19
-rw-r--r--src/tools/clippy/src/docs/strlen_on_c_strings.txt20
-rw-r--r--src/tools/clippy/src/docs/struct_excessive_bools.txt29
-rw-r--r--src/tools/clippy/src/docs/suboptimal_flops.txt50
-rw-r--r--src/tools/clippy/src/docs/suspicious_arithmetic_impl.txt17
-rw-r--r--src/tools/clippy/src/docs/suspicious_assignment_formatting.txt12
-rw-r--r--src/tools/clippy/src/docs/suspicious_else_formatting.txt30
-rw-r--r--src/tools/clippy/src/docs/suspicious_map.txt13
-rw-r--r--src/tools/clippy/src/docs/suspicious_op_assign_impl.txt15
-rw-r--r--src/tools/clippy/src/docs/suspicious_operation_groupings.txt41
-rw-r--r--src/tools/clippy/src/docs/suspicious_splitn.txt22
-rw-r--r--src/tools/clippy/src/docs/suspicious_to_owned.txt39
-rw-r--r--src/tools/clippy/src/docs/suspicious_unary_op_formatting.txt18
-rw-r--r--src/tools/clippy/src/docs/swap_ptr_to_ref.txt23
-rw-r--r--src/tools/clippy/src/docs/tabs_in_doc_comments.txt44
-rw-r--r--src/tools/clippy/src/docs/temporary_assignment.txt12
-rw-r--r--src/tools/clippy/src/docs/to_digit_is_some.txt15
-rw-r--r--src/tools/clippy/src/docs/to_string_in_format_args.txt17
-rw-r--r--src/tools/clippy/src/docs/todo.txt10
-rw-r--r--src/tools/clippy/src/docs/too_many_arguments.txt14
-rw-r--r--src/tools/clippy/src/docs/too_many_lines.txt17
-rw-r--r--src/tools/clippy/src/docs/toplevel_ref_arg.txt28
-rw-r--r--src/tools/clippy/src/docs/trailing_empty_array.txt22
-rw-r--r--src/tools/clippy/src/docs/trait_duplication_in_bounds.txt37
-rw-r--r--src/tools/clippy/src/docs/transmute_bytes_to_str.txt27
-rw-r--r--src/tools/clippy/src/docs/transmute_float_to_int.txt16
-rw-r--r--src/tools/clippy/src/docs/transmute_int_to_bool.txt16
-rw-r--r--src/tools/clippy/src/docs/transmute_int_to_char.txt27
-rw-r--r--src/tools/clippy/src/docs/transmute_int_to_float.txt16
-rw-r--r--src/tools/clippy/src/docs/transmute_num_to_bytes.txt16
-rw-r--r--src/tools/clippy/src/docs/transmute_ptr_to_ptr.txt21
-rw-r--r--src/tools/clippy/src/docs/transmute_ptr_to_ref.txt21
-rw-r--r--src/tools/clippy/src/docs/transmute_undefined_repr.txt22
-rw-r--r--src/tools/clippy/src/docs/transmutes_expressible_as_ptr_casts.txt16
-rw-r--r--src/tools/clippy/src/docs/transmuting_null.txt15
-rw-r--r--src/tools/clippy/src/docs/trim_split_whitespace.txt14
-rw-r--r--src/tools/clippy/src/docs/trivial_regex.txt18
-rw-r--r--src/tools/clippy/src/docs/trivially_copy_pass_by_ref.txt43
-rw-r--r--src/tools/clippy/src/docs/try_err.txt28
-rw-r--r--src/tools/clippy/src/docs/type_complexity.txt14
-rw-r--r--src/tools/clippy/src/docs/type_repetition_in_bounds.txt16
-rw-r--r--src/tools/clippy/src/docs/undocumented_unsafe_blocks.txt43
-rw-r--r--src/tools/clippy/src/docs/undropped_manually_drops.txt22
-rw-r--r--src/tools/clippy/src/docs/unicode_not_nfc.txt12
-rw-r--r--src/tools/clippy/src/docs/unimplemented.txt10
-rw-r--r--src/tools/clippy/src/docs/uninit_assumed_init.txt28
-rw-r--r--src/tools/clippy/src/docs/uninit_vec.txt41
-rw-r--r--src/tools/clippy/src/docs/uninlined_format_args.txt36
-rw-r--r--src/tools/clippy/src/docs/unit_arg.txt14
-rw-r--r--src/tools/clippy/src/docs/unit_cmp.txt33
-rw-r--r--src/tools/clippy/src/docs/unit_hash.txt20
-rw-r--r--src/tools/clippy/src/docs/unit_return_expecting_ord.txt20
-rw-r--r--src/tools/clippy/src/docs/unnecessary_cast.txt19
-rw-r--r--src/tools/clippy/src/docs/unnecessary_filter_map.txt23
-rw-r--r--src/tools/clippy/src/docs/unnecessary_find_map.txt23
-rw-r--r--src/tools/clippy/src/docs/unnecessary_fold.txt17
-rw-r--r--src/tools/clippy/src/docs/unnecessary_join.txt25
-rw-r--r--src/tools/clippy/src/docs/unnecessary_lazy_evaluations.txt32
-rw-r--r--src/tools/clippy/src/docs/unnecessary_mut_passed.txt17
-rw-r--r--src/tools/clippy/src/docs/unnecessary_operation.txt12
-rw-r--r--src/tools/clippy/src/docs/unnecessary_owned_empty_strings.txt16
-rw-r--r--src/tools/clippy/src/docs/unnecessary_self_imports.txt19
-rw-r--r--src/tools/clippy/src/docs/unnecessary_sort_by.txt21
-rw-r--r--src/tools/clippy/src/docs/unnecessary_to_owned.txt24
-rw-r--r--src/tools/clippy/src/docs/unnecessary_unwrap.txt20
-rw-r--r--src/tools/clippy/src/docs/unnecessary_wraps.txt36
-rw-r--r--src/tools/clippy/src/docs/unneeded_field_pattern.txt26
-rw-r--r--src/tools/clippy/src/docs/unneeded_wildcard_pattern.txt28
-rw-r--r--src/tools/clippy/src/docs/unnested_or_patterns.txt22
-rw-r--r--src/tools/clippy/src/docs/unreachable.txt10
-rw-r--r--src/tools/clippy/src/docs/unreadable_literal.txt16
-rw-r--r--src/tools/clippy/src/docs/unsafe_derive_deserialize.txt27
-rw-r--r--src/tools/clippy/src/docs/unsafe_removed_from_name.txt15
-rw-r--r--src/tools/clippy/src/docs/unseparated_literal_suffix.txt18
-rw-r--r--src/tools/clippy/src/docs/unsound_collection_transmute.txt25
-rw-r--r--src/tools/clippy/src/docs/unused_async.txt23
-rw-r--r--src/tools/clippy/src/docs/unused_format_specs.txt24
-rw-r--r--src/tools/clippy/src/docs/unused_io_amount.txt31
-rw-r--r--src/tools/clippy/src/docs/unused_peekable.txt26
-rw-r--r--src/tools/clippy/src/docs/unused_rounding.txt17
-rw-r--r--src/tools/clippy/src/docs/unused_self.txt23
-rw-r--r--src/tools/clippy/src/docs/unused_unit.txt18
-rw-r--r--src/tools/clippy/src/docs/unusual_byte_groupings.txt12
-rw-r--r--src/tools/clippy/src/docs/unwrap_in_result.txt39
-rw-r--r--src/tools/clippy/src/docs/unwrap_or_else_default.txt18
-rw-r--r--src/tools/clippy/src/docs/unwrap_used.txt37
-rw-r--r--src/tools/clippy/src/docs/upper_case_acronyms.txt25
-rw-r--r--src/tools/clippy/src/docs/use_debug.txt12
-rw-r--r--src/tools/clippy/src/docs/use_self.txt31
-rw-r--r--src/tools/clippy/src/docs/used_underscore_binding.txt19
-rw-r--r--src/tools/clippy/src/docs/useless_asref.txt17
-rw-r--r--src/tools/clippy/src/docs/useless_attribute.txt36
-rw-r--r--src/tools/clippy/src/docs/useless_conversion.txt17
-rw-r--r--src/tools/clippy/src/docs/useless_format.txt22
-rw-r--r--src/tools/clippy/src/docs/useless_let_if_seq.txt39
-rw-r--r--src/tools/clippy/src/docs/useless_transmute.txt12
-rw-r--r--src/tools/clippy/src/docs/useless_vec.txt18
-rw-r--r--src/tools/clippy/src/docs/vec_box.txt26
-rw-r--r--src/tools/clippy/src/docs/vec_init_then_push.txt23
-rw-r--r--src/tools/clippy/src/docs/vec_resize_to_zero.txt15
-rw-r--r--src/tools/clippy/src/docs/verbose_bit_mask.txt15
-rw-r--r--src/tools/clippy/src/docs/verbose_file_reads.txt17
-rw-r--r--src/tools/clippy/src/docs/vtable_address_comparisons.txt17
-rw-r--r--src/tools/clippy/src/docs/while_immutable_condition.txt20
-rw-r--r--src/tools/clippy/src/docs/while_let_loop.txt25
-rw-r--r--src/tools/clippy/src/docs/while_let_on_iterator.txt20
-rw-r--r--src/tools/clippy/src/docs/wildcard_dependencies.txt13
-rw-r--r--src/tools/clippy/src/docs/wildcard_enum_match_arm.txt25
-rw-r--r--src/tools/clippy/src/docs/wildcard_imports.txt45
-rw-r--r--src/tools/clippy/src/docs/wildcard_in_or_patterns.txt22
-rw-r--r--src/tools/clippy/src/docs/write_literal.txt17
-rw-r--r--src/tools/clippy/src/docs/write_with_newline.txt18
-rw-r--r--src/tools/clippy/src/docs/writeln_empty_string.txt16
-rw-r--r--src/tools/clippy/src/docs/wrong_self_convention.txt39
-rw-r--r--src/tools/clippy/src/docs/wrong_transmute.txt15
-rw-r--r--src/tools/clippy/src/docs/zero_divided_by_zero.txt15
-rw-r--r--src/tools/clippy/src/docs/zero_prefixed_literal.txt32
-rw-r--r--src/tools/clippy/src/docs/zero_ptr.txt16
-rw-r--r--src/tools/clippy/src/docs/zero_sized_map_values.txt24
-rw-r--r--src/tools/clippy/src/docs/zst_offset.txt11
-rw-r--r--src/tools/clippy/src/driver.rs56
-rw-r--r--src/tools/clippy/src/main.rs4
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr8
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr8
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr8
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr8
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr8
-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.stderr2
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr18
-rw-r--r--src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs11
-rw-r--r--src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr4
-rw-r--r--src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs23
-rw-r--r--src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr4
-rw-r--r--src/tools/clippy/tests/ui-toml/mut_key/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/mut_key/mut_key.rs53
-rw-r--r--src/tools/clippy/tests/ui-toml/print_macro/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/print_macro/print_macro.rs20
-rw-r--r--src/tools/clippy/tests/ui-toml/print_macro/print_macro.stderr18
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_disallowed_methods/clippy.toml6
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs30
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr50
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr3
-rw-r--r--src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs21
-rw-r--r--src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr32
-rw-r--r--src/tools/clippy/tests/ui-toml/vec_box_sized/test.rs5
-rw-r--r--src/tools/clippy/tests/ui-toml/vec_box_sized/test.stderr6
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.rs8
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.stderr110
-rw-r--r--src/tools/clippy/tests/ui/author/blocks.stdout2
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/doc_unsafe_macros.rs8
-rw-r--r--src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.rs2
-rw-r--r--src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr27
-rw-r--r--src/tools/clippy/tests/ui/bool_to_int_with_if.fixed22
-rw-r--r--src/tools/clippy/tests/ui/bool_to_int_with_if.rs22
-rw-r--r--src/tools/clippy/tests/ui/bool_to_int_with_if.stderr18
-rw-r--r--src/tools/clippy/tests/ui/cognitive_complexity.rs16
-rw-r--r--src/tools/clippy/tests/ui/cognitive_complexity.stderr18
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-2774.stderr2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-9746.rs15
-rw-r--r--src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr2
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs1
-rw-r--r--src/tools/clippy/tests/ui/doc_errors.stderr36
-rw-r--r--src/tools/clippy/tests/ui/doc_unnecessary_unsafe.rs148
-rw-r--r--src/tools/clippy/tests/ui/doc_unnecessary_unsafe.stderr51
-rw-r--r--src/tools/clippy/tests/ui/doc_unsafe.stderr34
-rw-r--r--src/tools/clippy/tests/ui/eq_op.rs1
-rw-r--r--src/tools/clippy/tests/ui/eq_op.stderr56
-rw-r--r--src/tools/clippy/tests/ui/equatable_if_let.fixed11
-rw-r--r--src/tools/clippy/tests/ui/equatable_if_let.rs7
-rw-r--r--src/tools/clippy/tests/ui/equatable_if_let.stderr42
-rw-r--r--src/tools/clippy/tests/ui/expect.stderr6
-rw-r--r--src/tools/clippy/tests/ui/explicit_auto_deref.fixed11
-rw-r--r--src/tools/clippy/tests/ui/explicit_auto_deref.rs11
-rw-r--r--src/tools/clippy/tests/ui/fn_params_excessive_bools.rs8
-rw-r--r--src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr22
-rw-r--r--src/tools/clippy/tests/ui/from_raw_with_void_ptr.rs34
-rw-r--r--src/tools/clippy/tests/ui/from_raw_with_void_ptr.stderr63
-rw-r--r--src/tools/clippy/tests/ui/get_unwrap.stderr26
-rw-r--r--src/tools/clippy/tests/ui/infallible_destructuring_match.fixed12
-rw-r--r--src/tools/clippy/tests/ui/infallible_destructuring_match.rs14
-rw-r--r--src/tools/clippy/tests/ui/infallible_destructuring_match.stderr16
-rw-r--r--src/tools/clippy/tests/ui/issue_4266.stderr4
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_drop.rs28
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_drop.stderr27
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_future.rs20
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_future.stderr27
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_lock.rs31
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_lock.stderr66
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_must_use.stderr24
-rw-r--r--src/tools/clippy/tests/ui/manual_flatten.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_instant_elapsed.fixed1
-rw-r--r--src/tools/clippy/tests/ui/manual_instant_elapsed.rs1
-rw-r--r--src/tools/clippy/tests/ui/manual_instant_elapsed.stderr4
-rw-r--r--src/tools/clippy/tests/ui/manual_is_ascii_check.fixed45
-rw-r--r--src/tools/clippy/tests/ui/manual_is_ascii_check.rs45
-rw-r--r--src/tools/clippy/tests/ui/manual_is_ascii_check.stderr70
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else.rs237
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else.stderr263
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.rs121
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.stderr58
-rw-r--r--src/tools/clippy/tests/ui/manual_ok_or.fixed1
-rw-r--r--src/tools/clippy/tests/ui/manual_ok_or.rs1
-rw-r--r--src/tools/clippy/tests/ui/manual_ok_or.stderr8
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.fixed1
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.stderr18
-rw-r--r--src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed7
-rw-r--r--src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs7
-rw-r--r--src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr28
-rw-r--r--src/tools/clippy/tests/ui/missing_panics_doc.stderr49
-rw-r--r--src/tools/clippy/tests/ui/mut_from_ref.rs2
-rw-r--r--src/tools/clippy/tests/ui/mut_mut.rs17
-rw-r--r--src/tools/clippy/tests/ui/mut_range_bound.rs2
-rw-r--r--src/tools/clippy/tests/ui/mut_range_bound.stderr2
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.fixed125
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.rs125
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.stderr8
-rw-r--r--src/tools/clippy/tests/ui/needless_borrowed_ref.fixed67
-rw-r--r--src/tools/clippy/tests/ui/needless_borrowed_ref.rs67
-rw-r--r--src/tools/clippy/tests/ui/needless_borrowed_ref.stderr113
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.fixed29
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.rs29
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.stderr26
-rw-r--r--src/tools/clippy/tests/ui/needless_collect_indirect.rs1
-rw-r--r--src/tools/clippy/tests/ui/needless_collect_indirect.stderr32
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.rs96
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.stderr246
-rw-r--r--src/tools/clippy/tests/ui/never_loop.rs21
-rw-r--r--src/tools/clippy/tests/ui/never_loop.stderr14
-rw-r--r--src/tools/clippy/tests/ui/new_ret_no_self.rs50
-rw-r--r--src/tools/clippy/tests/ui/new_ret_no_self.stderr18
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.fixed9
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.rs9
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.fixed16
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.rs16
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.stderr14
-rw-r--r--src/tools/clippy/tests/ui/question_mark.fixed3
-rw-r--r--src/tools/clippy/tests/ui/question_mark.rs3
-rw-r--r--src/tools/clippy/tests/ui/question_mark.stderr4
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed8
-rw-r--r--src/tools/clippy/tests/ui/rename.rs8
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr106
-rw-r--r--src/tools/clippy/tests/ui/result_large_err.rs12
-rw-r--r--src/tools/clippy/tests/ui/result_large_err.stderr30
-rw-r--r--src/tools/clippy/tests/ui/seek_from_current.fixed26
-rw-r--r--src/tools/clippy/tests/ui/seek_from_current.rs26
-rw-r--r--src/tools/clippy/tests/ui/seek_from_current.stderr10
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed137
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs137
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr22
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports.stderr12
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr15
-rw-r--r--src/tools/clippy/tests/ui/string_extend.fixed3
-rw-r--r--src/tools/clippy/tests/ui/string_extend.rs3
-rw-r--r--src/tools/clippy/tests/ui/string_extend.stderr8
-rw-r--r--src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.rs34
-rw-r--r--src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr51
-rw-r--r--src/tools/clippy/tests/ui/swap.fixed9
-rw-r--r--src/tools/clippy/tests/ui/swap.rs9
-rw-r--r--src/tools/clippy/tests/ui/transmute.rs2
-rw-r--r--src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs1
-rw-r--r--src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr36
-rw-r--r--src/tools/clippy/tests/ui/unchecked_duration_subtraction.fixed17
-rw-r--r--src/tools/clippy/tests/ui/unchecked_duration_subtraction.rs17
-rw-r--r--src/tools/clippy/tests/ui/unchecked_duration_subtraction.stderr28
-rw-r--r--src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs19
-rw-r--r--src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr26
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_join.stderr4
-rw-r--r--src/tools/clippy/tests/ui/unused_rounding.fixed5
-rw-r--r--src/tools/clippy/tests/ui/unused_rounding.rs5
-rw-r--r--src/tools/clippy/tests/ui/unused_rounding.stderr8
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.fixed7
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.rs7
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.stderr40
-rw-r--r--src/tools/clippy/tests/ui/unwrap.stderr6
-rw-r--r--src/tools/clippy/tests/ui/unwrap_expect_used.stderr12
-rw-r--r--src/tools/clippy/tests/ui/unwrap_or.rs2
-rw-r--r--src/tools/clippy/tests/ui/use_self_trait.fixed41
-rw-r--r--src/tools/clippy/tests/ui/use_self_trait.rs39
-rw-r--r--src/tools/clippy/tests/ui/use_self_trait.stderr14
-rw-r--r--src/tools/clippy/tests/ui/useless_attribute.fixed21
-rw-r--r--src/tools/clippy/tests/ui/useless_attribute.rs21
-rw-r--r--src/tools/clippy/tests/ui/useless_attribute.stderr6
-rw-r--r--src/tools/clippy/tests/versioncheck.rs15
-rw-r--r--src/tools/rust-analyzer/Cargo.lock116
-rw-r--r--src/tools/rust-analyzer/crates/base-db/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/cfg/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/src/lib.rs25
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs33
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs96
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs50
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs40
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs36
-rw-r--r--src/tools/rust-analyzer/crates/hir/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs27
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs37
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs16
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs38
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs270
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs20
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_format_string_arg.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs63
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/utils.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs159
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs32
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/line_index.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs60
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/useless_braces.rs20
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs22
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/ide/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_definition.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs243
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/moniker.rs20
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/references.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/signature_help.rs31
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/static_index.rs7
-rw-r--r--src/tools/rust-analyzer/crates/limit/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/mbe/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs89
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/syntax_bridge/tests.rs93
-rw-r--r--src/tools/rust-analyzer/crates/parser/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/paths/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/mod.rs2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs6
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-test/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-test/imp/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/profile/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/project-model/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs2
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs50
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/sysroot.rs27
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/tests.rs71
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs84
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cargo_target_spec.rs10
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/load_cargo.rs22
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs115
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs81
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs22
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/from_proto.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs19
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/line_index.rs60
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_utils.rs111
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs8
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/mem_docs.rs8
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs64
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs60
-rw-r--r--src/tools/rust-analyzer/crates/sourcegen/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/stdx/Cargo.toml4
-rw-r--r--src/tools/rust-analyzer/crates/syntax/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/rust.ungram7
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs46
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/text-edit/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/toolchain/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/tt/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/vfs/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/docs/dev/architecture.md6
-rw-r--r--src/tools/rust-analyzer/docs/user/generated_config.adoc20
-rw-r--r--src/tools/rust-analyzer/docs/user/manual.adoc2
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json46
-rw-r--r--src/tools/rust-analyzer/editors/code/src/client.ts42
-rw-r--r--src/tools/rust-analyzer/editors/code/src/config.ts3
-rw-r--r--src/tools/rust-analyzer/editors/code/src/ctx.ts3
-rw-r--r--src/tools/rust-analyzer/editors/code/src/main.ts24
-rw-r--r--src/tools/rust-analyzer/xtask/Cargo.toml2
-rw-r--r--src/tools/rustfmt/src/expr.rs2
1504 files changed, 18604 insertions, 24643 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 95e1787980a..d8612b3a256 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -446,7 +446,7 @@ dependencies = [
  "jobserver",
  "libc",
  "log",
- "miow 0.4.0",
+ "miow 0.5.0",
  "same-file",
  "shell-escape",
  "tempfile",
@@ -648,7 +648,7 @@ dependencies = [
 
 [[package]]
 name = "clippy"
-version = "0.1.66"
+version = "0.1.67"
 dependencies = [
  "clippy_lints",
  "clippy_utils",
@@ -685,16 +685,16 @@ dependencies = [
  "itertools",
  "opener",
  "shell-escape",
- "tempfile",
  "walkdir",
 ]
 
 [[package]]
 name = "clippy_lints"
-version = "0.1.66"
+version = "0.1.67"
 dependencies = [
  "cargo_metadata 0.14.0",
  "clippy_utils",
+ "declare_clippy_lint",
  "if_chain",
  "itertools",
  "pulldown-cmark",
@@ -713,7 +713,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_utils"
-version = "0.1.66"
+version = "0.1.67"
 dependencies = [
  "arrayvec",
  "if_chain",
@@ -1041,6 +1041,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69"
 
 [[package]]
+name = "declare_clippy_lint"
+version = "0.1.67"
+dependencies = [
+ "itertools",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "derive-new"
 version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2302,11 +2311,11 @@ dependencies = [
 
 [[package]]
 name = "miow"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7377f7792b3afb6a3cba68daa54ca23c032137010460d667fda53a8d66be00e"
+checksum = "52ffbca2f655e33c08be35d87278e5b18b89550a37dbd598c20db92f6a471123"
 dependencies = [
- "windows-sys 0.28.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -2583,7 +2592,7 @@ dependencies = [
  "libc",
  "redox_syscall",
  "smallvec",
- "windows-sys 0.42.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -2846,9 +2855,9 @@ checksum = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
 
 [[package]]
 name = "quote"
-version = "1.0.18"
+version = "1.0.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
+checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
 dependencies = [
  "proc-macro2",
 ]
@@ -3194,6 +3203,20 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustc_abi"
+version = "0.0.0"
+dependencies = [
+ "bitflags",
+ "rand 0.8.5",
+ "rand_xoshiro",
+ "rustc_data_structures",
+ "rustc_index",
+ "rustc_macros",
+ "rustc_serialize",
+ "tracing",
+]
+
+[[package]]
 name = "rustc_apfloat"
 version = "0.0.0"
 dependencies = [
@@ -4272,6 +4295,7 @@ name = "rustc_target"
 version = "0.0.0"
 dependencies = [
  "bitflags",
+ "rustc_abi",
  "rustc_data_structures",
  "rustc_feature",
  "rustc_index",
@@ -4327,6 +4351,7 @@ dependencies = [
  "rustc_infer",
  "rustc_middle",
  "rustc_span",
+ "rustc_target",
  "rustc_trait_selection",
  "smallvec",
  "tracing",
@@ -4351,8 +4376,6 @@ dependencies = [
 name = "rustc_ty_utils"
 version = "0.0.0"
 dependencies = [
- "rand 0.8.5",
- "rand_xoshiro",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_hir",
@@ -5554,30 +5577,17 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
 name = "windows-sys"
-version = "0.28.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82ca39602d5cbfa692c4b67e3bcbb2751477355141c1ed434c94da4186836ff6"
-dependencies = [
- "windows_aarch64_msvc 0.28.0",
- "windows_i686_gnu 0.28.0",
- "windows_i686_msvc 0.28.0",
- "windows_x86_64_gnu 0.28.0",
- "windows_x86_64_msvc 0.28.0",
-]
-
-[[package]]
-name = "windows-sys"
 version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
 dependencies = [
  "windows_aarch64_gnullvm",
- "windows_aarch64_msvc 0.42.0",
- "windows_i686_gnu 0.42.0",
- "windows_i686_msvc 0.42.0",
- "windows_x86_64_gnu 0.42.0",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
  "windows_x86_64_gnullvm",
- "windows_x86_64_msvc 0.42.0",
+ "windows_x86_64_msvc",
 ]
 
 [[package]]
@@ -5588,48 +5598,24 @@ checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.28.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2"
-
-[[package]]
-name = "windows_aarch64_msvc"
 version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.28.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a"
-
-[[package]]
-name = "windows_i686_gnu"
 version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.28.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64"
-
-[[package]]
-name = "windows_i686_msvc"
 version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.28.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954"
-
-[[package]]
-name = "windows_x86_64_gnu"
 version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
@@ -5642,12 +5628,6 @@ checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.28.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f"
-
-[[package]]
-name = "windows_x86_64_msvc"
 version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml
new file mode 100644
index 00000000000..48b199cb8ee
--- /dev/null
+++ b/compiler/rustc_abi/Cargo.toml
@@ -0,0 +1,24 @@
+[package]
+name = "rustc_abi"
+version = "0.0.0"
+edition = "2021"
+
+[dependencies]
+bitflags = "1.2.1"
+tracing = "0.1"
+rand = { version = "0.8.4", default-features = false, optional = true }
+rand_xoshiro = { version = "0.6.0", optional = true }
+rustc_data_structures = { path = "../rustc_data_structures", optional = true  }
+rustc_index = { path = "../rustc_index", default-features = false }
+rustc_macros = { path = "../rustc_macros", optional = true }
+rustc_serialize = { path = "../rustc_serialize", optional = true  }
+
+[features]
+default = ["nightly", "randomize"]
+randomize = ["rand", "rand_xoshiro"]
+nightly = [
+    "rustc_data_structures",
+    "rustc_index/nightly",
+    "rustc_macros",
+    "rustc_serialize",
+]
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
new file mode 100644
index 00000000000..39ea7a85be6
--- /dev/null
+++ b/compiler/rustc_abi/src/layout.rs
@@ -0,0 +1,947 @@
+use super::*;
+use std::{
+    borrow::Borrow,
+    cmp,
+    fmt::Debug,
+    iter,
+    ops::{Bound, Deref},
+};
+
+#[cfg(feature = "randomize")]
+use rand::{seq::SliceRandom, SeedableRng};
+#[cfg(feature = "randomize")]
+use rand_xoshiro::Xoshiro128StarStar;
+
+use tracing::debug;
+
+// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`.
+// This is used to go between `memory_index` (source field order to memory order)
+// and `inverse_memory_index` (memory order to source field order).
+// See also `FieldsShape::Arbitrary::memory_index` for more details.
+// FIXME(eddyb) build a better abstraction for permutations, if possible.
+fn invert_mapping(map: &[u32]) -> Vec<u32> {
+    let mut inverse = vec![0; map.len()];
+    for i in 0..map.len() {
+        inverse[map[i] as usize] = i as u32;
+    }
+    inverse
+}
+
+pub trait LayoutCalculator {
+    type TargetDataLayoutRef: Borrow<TargetDataLayout>;
+
+    fn delay_bug(&self, txt: &str);
+    fn current_data_layout(&self) -> Self::TargetDataLayoutRef;
+
+    fn scalar_pair<V: Idx>(&self, a: Scalar, b: Scalar) -> LayoutS<V> {
+        let dl = self.current_data_layout();
+        let dl = dl.borrow();
+        let b_align = b.align(dl);
+        let align = a.align(dl).max(b_align).max(dl.aggregate_align);
+        let b_offset = a.size(dl).align_to(b_align.abi);
+        let size = (b_offset + b.size(dl)).align_to(align.abi);
+
+        // HACK(nox): We iter on `b` and then `a` because `max_by_key`
+        // returns the last maximum.
+        let largest_niche = Niche::from_scalar(dl, b_offset, b)
+            .into_iter()
+            .chain(Niche::from_scalar(dl, Size::ZERO, a))
+            .max_by_key(|niche| niche.available(dl));
+
+        LayoutS {
+            variants: Variants::Single { index: V::new(0) },
+            fields: FieldsShape::Arbitrary {
+                offsets: vec![Size::ZERO, b_offset],
+                memory_index: vec![0, 1],
+            },
+            abi: Abi::ScalarPair(a, b),
+            largest_niche,
+            align,
+            size,
+        }
+    }
+
+    fn univariant<'a, V: Idx, F: Deref<Target = &'a LayoutS<V>> + Debug>(
+        &self,
+        dl: &TargetDataLayout,
+        fields: &[F],
+        repr: &ReprOptions,
+        kind: StructKind,
+    ) -> Option<LayoutS<V>> {
+        let pack = repr.pack;
+        let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
+        let mut inverse_memory_index: Vec<u32> = (0..fields.len() as u32).collect();
+        let optimize = !repr.inhibit_struct_field_reordering_opt();
+        if optimize {
+            let end =
+                if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
+            let optimizing = &mut inverse_memory_index[..end];
+            let effective_field_align = |f: &F| {
+                if let Some(pack) = pack {
+                    // return the packed alignment in bytes
+                    f.align.abi.min(pack).bytes()
+                } else {
+                    // returns log2(effective-align).
+                    // This is ok since `pack` applies to all fields equally.
+                    // The calculation assumes that size is an integer multiple of align, except for ZSTs.
+                    //
+                    // group [u8; 4] with align-4 or [u8; 6] with align-2 fields
+                    f.align.abi.bytes().max(f.size.bytes()).trailing_zeros() as u64
+                }
+            };
+
+            // If `-Z randomize-layout` was enabled for the type definition we can shuffle
+            // the field ordering to try and catch some code making assumptions about layouts
+            // we don't guarantee
+            if repr.can_randomize_type_layout() && cfg!(feature = "randomize") {
+                #[cfg(feature = "randomize")]
+                {
+                    // `ReprOptions.layout_seed` is a deterministic seed that we can use to
+                    // randomize field ordering with
+                    let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed);
+
+                    // Shuffle the ordering of the fields
+                    optimizing.shuffle(&mut rng);
+                }
+                // Otherwise we just leave things alone and actually optimize the type's fields
+            } else {
+                match kind {
+                    StructKind::AlwaysSized | StructKind::MaybeUnsized => {
+                        optimizing.sort_by_key(|&x| {
+                            // Place ZSTs first to avoid "interesting offsets",
+                            // especially with only one or two non-ZST fields.
+                            // Then place largest alignments first, largest niches within an alignment group last
+                            let f = &fields[x as usize];
+                            let niche_size = f.largest_niche.map_or(0, |n| n.available(dl));
+                            (!f.is_zst(), cmp::Reverse(effective_field_align(f)), niche_size)
+                        });
+                    }
+
+                    StructKind::Prefixed(..) => {
+                        // Sort in ascending alignment so that the layout stays optimal
+                        // regardless of the prefix.
+                        // And put the largest niche in an alignment group at the end
+                        // so it can be used as discriminant in jagged enums
+                        optimizing.sort_by_key(|&x| {
+                            let f = &fields[x as usize];
+                            let niche_size = f.largest_niche.map_or(0, |n| n.available(dl));
+                            (effective_field_align(f), niche_size)
+                        });
+                    }
+                }
+
+                // FIXME(Kixiron): We can always shuffle fields within a given alignment class
+                //                 regardless of the status of `-Z randomize-layout`
+            }
+        }
+        // inverse_memory_index holds field indices by increasing memory offset.
+        // That is, if field 5 has offset 0, the first element of inverse_memory_index is 5.
+        // We now write field offsets to the corresponding offset slot;
+        // field 5 with offset 0 puts 0 in offsets[5].
+        // At the bottom of this function, we invert `inverse_memory_index` to
+        // produce `memory_index` (see `invert_mapping`).
+        let mut sized = true;
+        let mut offsets = vec![Size::ZERO; fields.len()];
+        let mut offset = Size::ZERO;
+        let mut largest_niche = None;
+        let mut largest_niche_available = 0;
+        if let StructKind::Prefixed(prefix_size, prefix_align) = kind {
+            let prefix_align =
+                if let Some(pack) = pack { prefix_align.min(pack) } else { prefix_align };
+            align = align.max(AbiAndPrefAlign::new(prefix_align));
+            offset = prefix_size.align_to(prefix_align);
+        }
+        for &i in &inverse_memory_index {
+            let field = &fields[i as usize];
+            if !sized {
+                self.delay_bug(&format!(
+                    "univariant: field #{} comes after unsized field",
+                    offsets.len(),
+                ));
+            }
+
+            if field.is_unsized() {
+                sized = false;
+            }
+
+            // Invariant: offset < dl.obj_size_bound() <= 1<<61
+            let field_align = if let Some(pack) = pack {
+                field.align.min(AbiAndPrefAlign::new(pack))
+            } else {
+                field.align
+            };
+            offset = offset.align_to(field_align.abi);
+            align = align.max(field_align);
+
+            debug!("univariant offset: {:?} field: {:#?}", offset, field);
+            offsets[i as usize] = offset;
+
+            if let Some(mut niche) = field.largest_niche {
+                let available = niche.available(dl);
+                if available > largest_niche_available {
+                    largest_niche_available = available;
+                    niche.offset += offset;
+                    largest_niche = Some(niche);
+                }
+            }
+
+            offset = offset.checked_add(field.size, dl)?;
+        }
+        if let Some(repr_align) = repr.align {
+            align = align.max(AbiAndPrefAlign::new(repr_align));
+        }
+        debug!("univariant min_size: {:?}", offset);
+        let min_size = offset;
+        // As stated above, inverse_memory_index holds field indices by increasing offset.
+        // This makes it an already-sorted view of the offsets vec.
+        // To invert it, consider:
+        // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0.
+        // Field 5 would be the first element, so memory_index is i:
+        // Note: if we didn't optimize, it's already right.
+        let memory_index =
+            if optimize { invert_mapping(&inverse_memory_index) } else { inverse_memory_index };
+        let size = min_size.align_to(align.abi);
+        let mut abi = Abi::Aggregate { sized };
+        // Unpack newtype ABIs and find scalar pairs.
+        if sized && size.bytes() > 0 {
+            // All other fields must be ZSTs.
+            let mut non_zst_fields = fields.iter().enumerate().filter(|&(_, f)| !f.is_zst());
+
+            match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
+                // We have exactly one non-ZST field.
+                (Some((i, field)), None, None) => {
+                    // Field fills the struct and it has a scalar or scalar pair ABI.
+                    if offsets[i].bytes() == 0 && align.abi == field.align.abi && size == field.size
+                    {
+                        match field.abi {
+                            // For plain scalars, or vectors of them, we can't unpack
+                            // newtypes for `#[repr(C)]`, as that affects C ABIs.
+                            Abi::Scalar(_) | Abi::Vector { .. } if optimize => {
+                                abi = field.abi;
+                            }
+                            // But scalar pairs are Rust-specific and get
+                            // treated as aggregates by C ABIs anyway.
+                            Abi::ScalarPair(..) => {
+                                abi = field.abi;
+                            }
+                            _ => {}
+                        }
+                    }
+                }
+
+                // Two non-ZST fields, and they're both scalars.
+                (Some((i, a)), Some((j, b)), None) => {
+                    match (a.abi, b.abi) {
+                        (Abi::Scalar(a), Abi::Scalar(b)) => {
+                            // Order by the memory placement, not source order.
+                            let ((i, a), (j, b)) = if offsets[i] < offsets[j] {
+                                ((i, a), (j, b))
+                            } else {
+                                ((j, b), (i, a))
+                            };
+                            let pair = self.scalar_pair::<V>(a, b);
+                            let pair_offsets = match pair.fields {
+                                FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
+                                    assert_eq!(memory_index, &[0, 1]);
+                                    offsets
+                                }
+                                _ => panic!(),
+                            };
+                            if offsets[i] == pair_offsets[0]
+                                && offsets[j] == pair_offsets[1]
+                                && align == pair.align
+                                && size == pair.size
+                            {
+                                // We can use `ScalarPair` only when it matches our
+                                // already computed layout (including `#[repr(C)]`).
+                                abi = pair.abi;
+                            }
+                        }
+                        _ => {}
+                    }
+                }
+
+                _ => {}
+            }
+        }
+        if fields.iter().any(|f| f.abi.is_uninhabited()) {
+            abi = Abi::Uninhabited;
+        }
+        Some(LayoutS {
+            variants: Variants::Single { index: V::new(0) },
+            fields: FieldsShape::Arbitrary { offsets, memory_index },
+            abi,
+            largest_niche,
+            align,
+            size,
+        })
+    }
+
+    fn layout_of_never_type<V: Idx>(&self) -> LayoutS<V> {
+        let dl = self.current_data_layout();
+        let dl = dl.borrow();
+        LayoutS {
+            variants: Variants::Single { index: V::new(0) },
+            fields: FieldsShape::Primitive,
+            abi: Abi::Uninhabited,
+            largest_niche: None,
+            align: dl.i8_align,
+            size: Size::ZERO,
+        }
+    }
+
+    fn layout_of_struct_or_enum<'a, V: Idx, F: Deref<Target = &'a LayoutS<V>> + Debug>(
+        &self,
+        repr: &ReprOptions,
+        variants: &IndexVec<V, Vec<F>>,
+        is_enum: bool,
+        is_unsafe_cell: bool,
+        scalar_valid_range: (Bound<u128>, Bound<u128>),
+        discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
+        discriminants: impl Iterator<Item = (V, i128)>,
+        niche_optimize_enum: bool,
+        always_sized: bool,
+    ) -> Option<LayoutS<V>> {
+        let dl = self.current_data_layout();
+        let dl = dl.borrow();
+
+        let scalar_unit = |value: Primitive| {
+            let size = value.size(dl);
+            assert!(size.bits() <= 128);
+            Scalar::Initialized { value, valid_range: WrappingRange::full(size) }
+        };
+
+        // A variant is absent if it's uninhabited and only has ZST fields.
+        // Present uninhabited variants only require space for their fields,
+        // but *not* an encoding of the discriminant (e.g., a tag value).
+        // See issue #49298 for more details on the need to leave space
+        // for non-ZST uninhabited data (mostly partial initialization).
+        let absent = |fields: &[F]| {
+            let uninhabited = fields.iter().any(|f| f.abi.is_uninhabited());
+            let is_zst = fields.iter().all(|f| f.is_zst());
+            uninhabited && is_zst
+        };
+        let (present_first, present_second) = {
+            let mut present_variants = variants
+                .iter_enumerated()
+                .filter_map(|(i, v)| if absent(v) { None } else { Some(i) });
+            (present_variants.next(), present_variants.next())
+        };
+        let present_first = match present_first {
+            Some(present_first) => present_first,
+            // Uninhabited because it has no variants, or only absent ones.
+            None if is_enum => {
+                return Some(self.layout_of_never_type());
+            }
+            // If it's a struct, still compute a layout so that we can still compute the
+            // field offsets.
+            None => V::new(0),
+        };
+
+        let is_struct = !is_enum ||
+                    // Only one variant is present.
+                    (present_second.is_none() &&
+                        // Representation optimizations are allowed.
+                        !repr.inhibit_enum_layout_opt());
+        if is_struct {
+            // Struct, or univariant enum equivalent to a struct.
+            // (Typechecking will reject discriminant-sizing attrs.)
+
+            let v = present_first;
+            let kind = if is_enum || variants[v].is_empty() {
+                StructKind::AlwaysSized
+            } else {
+                if !always_sized { StructKind::MaybeUnsized } else { StructKind::AlwaysSized }
+            };
+
+            let mut st = self.univariant(dl, &variants[v], &repr, kind)?;
+            st.variants = Variants::Single { index: v };
+
+            if is_unsafe_cell {
+                let hide_niches = |scalar: &mut _| match scalar {
+                    Scalar::Initialized { value, valid_range } => {
+                        *valid_range = WrappingRange::full(value.size(dl))
+                    }
+                    // Already doesn't have any niches
+                    Scalar::Union { .. } => {}
+                };
+                match &mut st.abi {
+                    Abi::Uninhabited => {}
+                    Abi::Scalar(scalar) => hide_niches(scalar),
+                    Abi::ScalarPair(a, b) => {
+                        hide_niches(a);
+                        hide_niches(b);
+                    }
+                    Abi::Vector { element, count: _ } => hide_niches(element),
+                    Abi::Aggregate { sized: _ } => {}
+                }
+                st.largest_niche = None;
+                return Some(st);
+            }
+
+            let (start, end) = scalar_valid_range;
+            match st.abi {
+                Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => {
+                    // the asserts ensure that we are not using the
+                    // `#[rustc_layout_scalar_valid_range(n)]`
+                    // attribute to widen the range of anything as that would probably
+                    // result in UB somewhere
+                    // FIXME(eddyb) the asserts are probably not needed,
+                    // as larger validity ranges would result in missed
+                    // optimizations, *not* wrongly assuming the inner
+                    // value is valid. e.g. unions enlarge validity ranges,
+                    // because the values may be uninitialized.
+                    if let Bound::Included(start) = start {
+                        // FIXME(eddyb) this might be incorrect - it doesn't
+                        // account for wrap-around (end < start) ranges.
+                        let valid_range = scalar.valid_range_mut();
+                        assert!(valid_range.start <= start);
+                        valid_range.start = start;
+                    }
+                    if let Bound::Included(end) = end {
+                        // FIXME(eddyb) this might be incorrect - it doesn't
+                        // account for wrap-around (end < start) ranges.
+                        let valid_range = scalar.valid_range_mut();
+                        assert!(valid_range.end >= end);
+                        valid_range.end = end;
+                    }
+
+                    // Update `largest_niche` if we have introduced a larger niche.
+                    let niche = Niche::from_scalar(dl, Size::ZERO, *scalar);
+                    if let Some(niche) = niche {
+                        match st.largest_niche {
+                            Some(largest_niche) => {
+                                // Replace the existing niche even if they're equal,
+                                // because this one is at a lower offset.
+                                if largest_niche.available(dl) <= niche.available(dl) {
+                                    st.largest_niche = Some(niche);
+                                }
+                            }
+                            None => st.largest_niche = Some(niche),
+                        }
+                    }
+                }
+                _ => assert!(
+                    start == Bound::Unbounded && end == Bound::Unbounded,
+                    "nonscalar layout for layout_scalar_valid_range type: {:#?}",
+                    st,
+                ),
+            }
+
+            return Some(st);
+        }
+
+        // At this point, we have handled all unions and
+        // structs. (We have also handled univariant enums
+        // that allow representation optimization.)
+        assert!(is_enum);
+
+        // Until we've decided whether to use the tagged or
+        // niche filling LayoutS, we don't want to intern the
+        // variant layouts, so we can't store them in the
+        // overall LayoutS. Store the overall LayoutS
+        // and the variant LayoutSs here until then.
+        struct TmpLayout<V: Idx> {
+            layout: LayoutS<V>,
+            variants: IndexVec<V, LayoutS<V>>,
+        }
+
+        let calculate_niche_filling_layout = || -> Option<TmpLayout<V>> {
+            if niche_optimize_enum {
+                return None;
+            }
+
+            if variants.len() < 2 {
+                return None;
+            }
+
+            let mut align = dl.aggregate_align;
+            let mut variant_layouts = variants
+                .iter_enumerated()
+                .map(|(j, v)| {
+                    let mut st = self.univariant(dl, v, &repr, StructKind::AlwaysSized)?;
+                    st.variants = Variants::Single { index: j };
+
+                    align = align.max(st.align);
+
+                    Some(st)
+                })
+                .collect::<Option<IndexVec<V, _>>>()?;
+
+            let largest_variant_index = variant_layouts
+                .iter_enumerated()
+                .max_by_key(|(_i, layout)| layout.size.bytes())
+                .map(|(i, _layout)| i)?;
+
+            let all_indices = (0..=variants.len() - 1).map(V::new);
+            let needs_disc = |index: V| index != largest_variant_index && !absent(&variants[index]);
+            let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap().index()
+                ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap().index();
+
+            let count = niche_variants.size_hint().1.unwrap() as u128;
+
+            // Find the field with the largest niche
+            let (field_index, niche, (niche_start, niche_scalar)) = variants[largest_variant_index]
+                .iter()
+                .enumerate()
+                .filter_map(|(j, field)| Some((j, field.largest_niche?)))
+                .max_by_key(|(_, niche)| niche.available(dl))
+                .and_then(|(j, niche)| Some((j, niche, niche.reserve(dl, count)?)))?;
+            let niche_offset =
+                niche.offset + variant_layouts[largest_variant_index].fields.offset(field_index);
+            let niche_size = niche.value.size(dl);
+            let size = variant_layouts[largest_variant_index].size.align_to(align.abi);
+
+            let all_variants_fit = variant_layouts.iter_enumerated_mut().all(|(i, layout)| {
+                if i == largest_variant_index {
+                    return true;
+                }
+
+                layout.largest_niche = None;
+
+                if layout.size <= niche_offset {
+                    // This variant will fit before the niche.
+                    return true;
+                }
+
+                // Determine if it'll fit after the niche.
+                let this_align = layout.align.abi;
+                let this_offset = (niche_offset + niche_size).align_to(this_align);
+
+                if this_offset + layout.size > size {
+                    return false;
+                }
+
+                // It'll fit, but we need to make some adjustments.
+                match layout.fields {
+                    FieldsShape::Arbitrary { ref mut offsets, .. } => {
+                        for (j, offset) in offsets.iter_mut().enumerate() {
+                            if !variants[i][j].is_zst() {
+                                *offset += this_offset;
+                            }
+                        }
+                    }
+                    _ => {
+                        panic!("Layout of fields should be Arbitrary for variants")
+                    }
+                }
+
+                // It can't be a Scalar or ScalarPair because the offset isn't 0.
+                if !layout.abi.is_uninhabited() {
+                    layout.abi = Abi::Aggregate { sized: true };
+                }
+                layout.size += this_offset;
+
+                true
+            });
+
+            if !all_variants_fit {
+                return None;
+            }
+
+            let largest_niche = Niche::from_scalar(dl, niche_offset, niche_scalar);
+
+            let others_zst = variant_layouts
+                .iter_enumerated()
+                .all(|(i, layout)| i == largest_variant_index || layout.size == Size::ZERO);
+            let same_size = size == variant_layouts[largest_variant_index].size;
+            let same_align = align == variant_layouts[largest_variant_index].align;
+
+            let abi = if variant_layouts.iter().all(|v| v.abi.is_uninhabited()) {
+                Abi::Uninhabited
+            } else if same_size && same_align && others_zst {
+                match variant_layouts[largest_variant_index].abi {
+                    // When the total alignment and size match, we can use the
+                    // same ABI as the scalar variant with the reserved niche.
+                    Abi::Scalar(_) => Abi::Scalar(niche_scalar),
+                    Abi::ScalarPair(first, second) => {
+                        // Only the niche is guaranteed to be initialised,
+                        // so use union layouts for the other primitive.
+                        if niche_offset == Size::ZERO {
+                            Abi::ScalarPair(niche_scalar, second.to_union())
+                        } else {
+                            Abi::ScalarPair(first.to_union(), niche_scalar)
+                        }
+                    }
+                    _ => Abi::Aggregate { sized: true },
+                }
+            } else {
+                Abi::Aggregate { sized: true }
+            };
+
+            let layout = LayoutS {
+                variants: Variants::Multiple {
+                    tag: niche_scalar,
+                    tag_encoding: TagEncoding::Niche {
+                        untagged_variant: largest_variant_index,
+                        niche_variants: (V::new(*niche_variants.start())
+                            ..=V::new(*niche_variants.end())),
+                        niche_start,
+                    },
+                    tag_field: 0,
+                    variants: IndexVec::new(),
+                },
+                fields: FieldsShape::Arbitrary {
+                    offsets: vec![niche_offset],
+                    memory_index: vec![0],
+                },
+                abi,
+                largest_niche,
+                size,
+                align,
+            };
+
+            Some(TmpLayout { layout, variants: variant_layouts })
+        };
+
+        let niche_filling_layout = calculate_niche_filling_layout();
+
+        let (mut min, mut max) = (i128::MAX, i128::MIN);
+        let discr_type = repr.discr_type();
+        let bits = Integer::from_attr(dl, discr_type).size().bits();
+        for (i, mut val) in discriminants {
+            if variants[i].iter().any(|f| f.abi.is_uninhabited()) {
+                continue;
+            }
+            if discr_type.is_signed() {
+                // sign extend the raw representation to be an i128
+                val = (val << (128 - bits)) >> (128 - bits);
+            }
+            if val < min {
+                min = val;
+            }
+            if val > max {
+                max = val;
+            }
+        }
+        // We might have no inhabited variants, so pretend there's at least one.
+        if (min, max) == (i128::MAX, i128::MIN) {
+            min = 0;
+            max = 0;
+        }
+        assert!(min <= max, "discriminant range is {}...{}", min, max);
+        let (min_ity, signed) = discr_range_of_repr(min, max); //Integer::repr_discr(tcx, ty, &repr, min, max);
+
+        let mut align = dl.aggregate_align;
+        let mut size = Size::ZERO;
+
+        // We're interested in the smallest alignment, so start large.
+        let mut start_align = Align::from_bytes(256).unwrap();
+        assert_eq!(Integer::for_align(dl, start_align), None);
+
+        // repr(C) on an enum tells us to make a (tag, union) layout,
+        // so we need to grow the prefix alignment to be at least
+        // the alignment of the union. (This value is used both for
+        // determining the alignment of the overall enum, and the
+        // determining the alignment of the payload after the tag.)
+        let mut prefix_align = min_ity.align(dl).abi;
+        if repr.c() {
+            for fields in variants {
+                for field in fields {
+                    prefix_align = prefix_align.max(field.align.abi);
+                }
+            }
+        }
+
+        // Create the set of structs that represent each variant.
+        let mut layout_variants = variants
+            .iter_enumerated()
+            .map(|(i, field_layouts)| {
+                let mut st = self.univariant(
+                    dl,
+                    &field_layouts,
+                    &repr,
+                    StructKind::Prefixed(min_ity.size(), prefix_align),
+                )?;
+                st.variants = Variants::Single { index: i };
+                // Find the first field we can't move later
+                // to make room for a larger discriminant.
+                for field in st.fields.index_by_increasing_offset().map(|j| &field_layouts[j]) {
+                    if !field.is_zst() || field.align.abi.bytes() != 1 {
+                        start_align = start_align.min(field.align.abi);
+                        break;
+                    }
+                }
+                size = cmp::max(size, st.size);
+                align = align.max(st.align);
+                Some(st)
+            })
+            .collect::<Option<IndexVec<V, _>>>()?;
+
+        // Align the maximum variant size to the largest alignment.
+        size = size.align_to(align.abi);
+
+        if size.bytes() >= dl.obj_size_bound() {
+            return None;
+        }
+
+        let typeck_ity = Integer::from_attr(dl, repr.discr_type());
+        if typeck_ity < min_ity {
+            // It is a bug if Layout decided on a greater discriminant size than typeck for
+            // some reason at this point (based on values discriminant can take on). Mostly
+            // because this discriminant will be loaded, and then stored into variable of
+            // type calculated by typeck. Consider such case (a bug): typeck decided on
+            // byte-sized discriminant, but layout thinks we need a 16-bit to store all
+            // discriminant values. That would be a bug, because then, in codegen, in order
+            // to store this 16-bit discriminant into 8-bit sized temporary some of the
+            // space necessary to represent would have to be discarded (or layout is wrong
+            // on thinking it needs 16 bits)
+            panic!(
+                "layout decided on a larger discriminant type ({:?}) than typeck ({:?})",
+                min_ity, typeck_ity
+            );
+            // However, it is fine to make discr type however large (as an optimisation)
+            // after this point – we’ll just truncate the value we load in codegen.
+        }
+
+        // Check to see if we should use a different type for the
+        // discriminant. We can safely use a type with the same size
+        // as the alignment of the first field of each variant.
+        // We increase the size of the discriminant to avoid LLVM copying
+        // padding when it doesn't need to. This normally causes unaligned
+        // load/stores and excessive memcpy/memset operations. By using a
+        // bigger integer size, LLVM can be sure about its contents and
+        // won't be so conservative.
+
+        // Use the initial field alignment
+        let mut ity = if repr.c() || repr.int.is_some() {
+            min_ity
+        } else {
+            Integer::for_align(dl, start_align).unwrap_or(min_ity)
+        };
+
+        // If the alignment is not larger than the chosen discriminant size,
+        // don't use the alignment as the final size.
+        if ity <= min_ity {
+            ity = min_ity;
+        } else {
+            // Patch up the variants' first few fields.
+            let old_ity_size = min_ity.size();
+            let new_ity_size = ity.size();
+            for variant in &mut layout_variants {
+                match variant.fields {
+                    FieldsShape::Arbitrary { ref mut offsets, .. } => {
+                        for i in offsets {
+                            if *i <= old_ity_size {
+                                assert_eq!(*i, old_ity_size);
+                                *i = new_ity_size;
+                            }
+                        }
+                        // We might be making the struct larger.
+                        if variant.size <= old_ity_size {
+                            variant.size = new_ity_size;
+                        }
+                    }
+                    _ => panic!(),
+                }
+            }
+        }
+
+        let tag_mask = ity.size().unsigned_int_max();
+        let tag = Scalar::Initialized {
+            value: Int(ity, signed),
+            valid_range: WrappingRange {
+                start: (min as u128 & tag_mask),
+                end: (max as u128 & tag_mask),
+            },
+        };
+        let mut abi = Abi::Aggregate { sized: true };
+
+        if layout_variants.iter().all(|v| v.abi.is_uninhabited()) {
+            abi = Abi::Uninhabited;
+        } else if tag.size(dl) == size {
+            // Make sure we only use scalar layout when the enum is entirely its
+            // own tag (i.e. it has no padding nor any non-ZST variant fields).
+            abi = Abi::Scalar(tag);
+        } else {
+            // Try to use a ScalarPair for all tagged enums.
+            let mut common_prim = None;
+            let mut common_prim_initialized_in_all_variants = true;
+            for (field_layouts, layout_variant) in iter::zip(&*variants, &layout_variants) {
+                let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else {
+                    panic!();
+                };
+                let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst());
+                let (field, offset) = match (fields.next(), fields.next()) {
+                    (None, None) => {
+                        common_prim_initialized_in_all_variants = false;
+                        continue;
+                    }
+                    (Some(pair), None) => pair,
+                    _ => {
+                        common_prim = None;
+                        break;
+                    }
+                };
+                let prim = match field.abi {
+                    Abi::Scalar(scalar) => {
+                        common_prim_initialized_in_all_variants &=
+                            matches!(scalar, Scalar::Initialized { .. });
+                        scalar.primitive()
+                    }
+                    _ => {
+                        common_prim = None;
+                        break;
+                    }
+                };
+                if let Some(pair) = common_prim {
+                    // This is pretty conservative. We could go fancier
+                    // by conflating things like i32 and u32, or even
+                    // realising that (u8, u8) could just cohabit with
+                    // u16 or even u32.
+                    if pair != (prim, offset) {
+                        common_prim = None;
+                        break;
+                    }
+                } else {
+                    common_prim = Some((prim, offset));
+                }
+            }
+            if let Some((prim, offset)) = common_prim {
+                let prim_scalar = if common_prim_initialized_in_all_variants {
+                    scalar_unit(prim)
+                } else {
+                    // Common prim might be uninit.
+                    Scalar::Union { value: prim }
+                };
+                let pair = self.scalar_pair::<V>(tag, prim_scalar);
+                let pair_offsets = match pair.fields {
+                    FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
+                        assert_eq!(memory_index, &[0, 1]);
+                        offsets
+                    }
+                    _ => panic!(),
+                };
+                if pair_offsets[0] == Size::ZERO
+                    && pair_offsets[1] == *offset
+                    && align == pair.align
+                    && size == pair.size
+                {
+                    // We can use `ScalarPair` only when it matches our
+                    // already computed layout (including `#[repr(C)]`).
+                    abi = pair.abi;
+                }
+            }
+        }
+
+        // If we pick a "clever" (by-value) ABI, we might have to adjust the ABI of the
+        // variants to ensure they are consistent. This is because a downcast is
+        // semantically a NOP, and thus should not affect layout.
+        if matches!(abi, Abi::Scalar(..) | Abi::ScalarPair(..)) {
+            for variant in &mut layout_variants {
+                // We only do this for variants with fields; the others are not accessed anyway.
+                // Also do not overwrite any already existing "clever" ABIs.
+                if variant.fields.count() > 0 && matches!(variant.abi, Abi::Aggregate { .. }) {
+                    variant.abi = abi;
+                    // Also need to bump up the size and alignment, so that the entire value fits in here.
+                    variant.size = cmp::max(variant.size, size);
+                    variant.align.abi = cmp::max(variant.align.abi, align.abi);
+                }
+            }
+        }
+
+        let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag);
+
+        let tagged_layout = LayoutS {
+            variants: Variants::Multiple {
+                tag,
+                tag_encoding: TagEncoding::Direct,
+                tag_field: 0,
+                variants: IndexVec::new(),
+            },
+            fields: FieldsShape::Arbitrary { offsets: vec![Size::ZERO], memory_index: vec![0] },
+            largest_niche,
+            abi,
+            align,
+            size,
+        };
+
+        let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants };
+
+        let mut best_layout = match (tagged_layout, niche_filling_layout) {
+            (tl, Some(nl)) => {
+                // Pick the smaller layout; otherwise,
+                // pick the layout with the larger niche; otherwise,
+                // pick tagged as it has simpler codegen.
+                use cmp::Ordering::*;
+                let niche_size = |tmp_l: &TmpLayout<V>| {
+                    tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl))
+                };
+                match (tl.layout.size.cmp(&nl.layout.size), niche_size(&tl).cmp(&niche_size(&nl))) {
+                    (Greater, _) => nl,
+                    (Equal, Less) => nl,
+                    _ => tl,
+                }
+            }
+            (tl, None) => tl,
+        };
+
+        // Now we can intern the variant layouts and store them in the enum layout.
+        best_layout.layout.variants = match best_layout.layout.variants {
+            Variants::Multiple { tag, tag_encoding, tag_field, .. } => {
+                Variants::Multiple { tag, tag_encoding, tag_field, variants: best_layout.variants }
+            }
+            _ => panic!(),
+        };
+        Some(best_layout.layout)
+    }
+
+    fn layout_of_union<'a, V: Idx, F: Deref<Target = &'a LayoutS<V>> + Debug>(
+        &self,
+        repr: &ReprOptions,
+        variants: &IndexVec<V, Vec<F>>,
+    ) -> Option<LayoutS<V>> {
+        let dl = self.current_data_layout();
+        let dl = dl.borrow();
+        let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
+
+        if let Some(repr_align) = repr.align {
+            align = align.max(AbiAndPrefAlign::new(repr_align));
+        }
+
+        let optimize = !repr.inhibit_union_abi_opt();
+        let mut size = Size::ZERO;
+        let mut abi = Abi::Aggregate { sized: true };
+        let index = V::new(0);
+        for field in &variants[index] {
+            assert!(field.is_sized());
+            align = align.max(field.align);
+
+            // If all non-ZST fields have the same ABI, forward this ABI
+            if optimize && !field.is_zst() {
+                // Discard valid range information and allow undef
+                let field_abi = match field.abi {
+                    Abi::Scalar(x) => Abi::Scalar(x.to_union()),
+                    Abi::ScalarPair(x, y) => Abi::ScalarPair(x.to_union(), y.to_union()),
+                    Abi::Vector { element: x, count } => {
+                        Abi::Vector { element: x.to_union(), count }
+                    }
+                    Abi::Uninhabited | Abi::Aggregate { .. } => Abi::Aggregate { sized: true },
+                };
+
+                if size == Size::ZERO {
+                    // first non ZST: initialize 'abi'
+                    abi = field_abi;
+                } else if abi != field_abi {
+                    // different fields have different ABI: reset to Aggregate
+                    abi = Abi::Aggregate { sized: true };
+                }
+            }
+
+            size = cmp::max(size, field.size);
+        }
+
+        if let Some(pack) = repr.pack {
+            align = align.min(AbiAndPrefAlign::new(pack));
+        }
+
+        Some(LayoutS {
+            variants: Variants::Single { index },
+            fields: FieldsShape::Union(NonZeroUsize::new(variants[index].len())?),
+            abi,
+            largest_niche: None,
+            align,
+            size: size.align_to(align.abi),
+        })
+    }
+}
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
new file mode 100644
index 00000000000..4f4a4bf314f
--- /dev/null
+++ b/compiler/rustc_abi/src/lib.rs
@@ -0,0 +1,1399 @@
+#![cfg_attr(feature = "nightly", feature(step_trait, rustc_attrs, min_specialization))]
+
+use std::convert::{TryFrom, TryInto};
+use std::fmt;
+#[cfg(feature = "nightly")]
+use std::iter::Step;
+use std::num::{NonZeroUsize, ParseIntError};
+use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub};
+use std::str::FromStr;
+
+use bitflags::bitflags;
+use rustc_index::vec::{Idx, IndexVec};
+#[cfg(feature = "nightly")]
+use rustc_macros::HashStable_Generic;
+#[cfg(feature = "nightly")]
+use rustc_macros::{Decodable, Encodable};
+
+mod layout;
+
+pub use layout::LayoutCalculator;
+
+/// Requirements for a `StableHashingContext` to be used in this crate.
+/// This is a hack to allow using the `HashStable_Generic` derive macro
+/// instead of implementing everything in `rustc_middle`.
+pub trait HashStableContext {}
+
+use Integer::*;
+use Primitive::*;
+
+bitflags! {
+    #[derive(Default)]
+    #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
+    pub struct ReprFlags: u8 {
+        const IS_C               = 1 << 0;
+        const IS_SIMD            = 1 << 1;
+        const IS_TRANSPARENT     = 1 << 2;
+        // Internal only for now. If true, don't reorder fields.
+        const IS_LINEAR          = 1 << 3;
+        // If true, the type's layout can be randomized using
+        // the seed stored in `ReprOptions.layout_seed`
+        const RANDOMIZE_LAYOUT   = 1 << 4;
+        // Any of these flags being set prevent field reordering optimisation.
+        const IS_UNOPTIMISABLE   = ReprFlags::IS_C.bits
+                                 | ReprFlags::IS_SIMD.bits
+                                 | ReprFlags::IS_LINEAR.bits;
+    }
+}
+
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
+pub enum IntegerType {
+    /// Pointer sized integer type, i.e. isize and usize. The field shows signedness, that
+    /// is, `Pointer(true)` is isize.
+    Pointer(bool),
+    /// Fix sized integer type, e.g. i8, u32, i128 The bool field shows signedness, `Fixed(I8, false)` means `u8`
+    Fixed(Integer, bool),
+}
+
+impl IntegerType {
+    pub fn is_signed(&self) -> bool {
+        match self {
+            IntegerType::Pointer(b) => *b,
+            IntegerType::Fixed(_, b) => *b,
+        }
+    }
+}
+
+/// Represents the repr options provided by the user,
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
+pub struct ReprOptions {
+    pub int: Option<IntegerType>,
+    pub align: Option<Align>,
+    pub pack: Option<Align>,
+    pub flags: ReprFlags,
+    /// The seed to be used for randomizing a type's layout
+    ///
+    /// Note: This could technically be a `[u8; 16]` (a `u128`) which would
+    /// be the "most accurate" hash as it'd encompass the item and crate
+    /// hash without loss, but it does pay the price of being larger.
+    /// Everything's a tradeoff, a `u64` seed should be sufficient for our
+    /// purposes (primarily `-Z randomize-layout`)
+    pub field_shuffle_seed: u64,
+}
+
+impl ReprOptions {
+    #[inline]
+    pub fn simd(&self) -> bool {
+        self.flags.contains(ReprFlags::IS_SIMD)
+    }
+
+    #[inline]
+    pub fn c(&self) -> bool {
+        self.flags.contains(ReprFlags::IS_C)
+    }
+
+    #[inline]
+    pub fn packed(&self) -> bool {
+        self.pack.is_some()
+    }
+
+    #[inline]
+    pub fn transparent(&self) -> bool {
+        self.flags.contains(ReprFlags::IS_TRANSPARENT)
+    }
+
+    #[inline]
+    pub fn linear(&self) -> bool {
+        self.flags.contains(ReprFlags::IS_LINEAR)
+    }
+
+    /// Returns the discriminant type, given these `repr` options.
+    /// This must only be called on enums!
+    pub fn discr_type(&self) -> IntegerType {
+        self.int.unwrap_or(IntegerType::Pointer(true))
+    }
+
+    /// Returns `true` if this `#[repr()]` should inhabit "smart enum
+    /// layout" optimizations, such as representing `Foo<&T>` as a
+    /// single pointer.
+    pub fn inhibit_enum_layout_opt(&self) -> bool {
+        self.c() || self.int.is_some()
+    }
+
+    /// Returns `true` if this `#[repr()]` should inhibit struct field reordering
+    /// optimizations, such as with `repr(C)`, `repr(packed(1))`, or `repr(<int>)`.
+    pub fn inhibit_struct_field_reordering_opt(&self) -> bool {
+        if let Some(pack) = self.pack {
+            if pack.bytes() == 1 {
+                return true;
+            }
+        }
+
+        self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some()
+    }
+
+    /// Returns `true` if this type is valid for reordering and `-Z randomize-layout`
+    /// was enabled for its declaration crate
+    pub fn can_randomize_type_layout(&self) -> bool {
+        !self.inhibit_struct_field_reordering_opt()
+            && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT)
+    }
+
+    /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations.
+    pub fn inhibit_union_abi_opt(&self) -> bool {
+        self.c()
+    }
+}
+
+/// Parsed [Data layout](https://llvm.org/docs/LangRef.html#data-layout)
+/// for a target, which contains everything needed to compute layouts.
+#[derive(Debug, PartialEq, Eq)]
+pub struct TargetDataLayout {
+    pub endian: Endian,
+    pub i1_align: AbiAndPrefAlign,
+    pub i8_align: AbiAndPrefAlign,
+    pub i16_align: AbiAndPrefAlign,
+    pub i32_align: AbiAndPrefAlign,
+    pub i64_align: AbiAndPrefAlign,
+    pub i128_align: AbiAndPrefAlign,
+    pub f32_align: AbiAndPrefAlign,
+    pub f64_align: AbiAndPrefAlign,
+    pub pointer_size: Size,
+    pub pointer_align: AbiAndPrefAlign,
+    pub aggregate_align: AbiAndPrefAlign,
+
+    /// Alignments for vector types.
+    pub vector_align: Vec<(Size, AbiAndPrefAlign)>,
+
+    pub instruction_address_space: AddressSpace,
+
+    /// Minimum size of #[repr(C)] enums (default I32 bits)
+    pub c_enum_min_size: Integer,
+}
+
+impl Default for TargetDataLayout {
+    /// Creates an instance of `TargetDataLayout`.
+    fn default() -> TargetDataLayout {
+        let align = |bits| Align::from_bits(bits).unwrap();
+        TargetDataLayout {
+            endian: Endian::Big,
+            i1_align: AbiAndPrefAlign::new(align(8)),
+            i8_align: AbiAndPrefAlign::new(align(8)),
+            i16_align: AbiAndPrefAlign::new(align(16)),
+            i32_align: AbiAndPrefAlign::new(align(32)),
+            i64_align: AbiAndPrefAlign { abi: align(32), pref: align(64) },
+            i128_align: AbiAndPrefAlign { abi: align(32), pref: align(64) },
+            f32_align: AbiAndPrefAlign::new(align(32)),
+            f64_align: AbiAndPrefAlign::new(align(64)),
+            pointer_size: Size::from_bits(64),
+            pointer_align: AbiAndPrefAlign::new(align(64)),
+            aggregate_align: AbiAndPrefAlign { abi: align(0), pref: align(64) },
+            vector_align: vec![
+                (Size::from_bits(64), AbiAndPrefAlign::new(align(64))),
+                (Size::from_bits(128), AbiAndPrefAlign::new(align(128))),
+            ],
+            instruction_address_space: AddressSpace::DATA,
+            c_enum_min_size: Integer::I32,
+        }
+    }
+}
+
+pub enum TargetDataLayoutErrors<'a> {
+    InvalidAddressSpace { addr_space: &'a str, cause: &'a str, err: ParseIntError },
+    InvalidBits { kind: &'a str, bit: &'a str, cause: &'a str, err: ParseIntError },
+    MissingAlignment { cause: &'a str },
+    InvalidAlignment { cause: &'a str, err: String },
+    InconsistentTargetArchitecture { dl: &'a str, target: &'a str },
+    InconsistentTargetPointerWidth { pointer_size: u64, target: u32 },
+    InvalidBitsSize { err: String },
+}
+
+impl TargetDataLayout {
+    /// Returns exclusive upper bound on object size.
+    ///
+    /// The theoretical maximum object size is defined as the maximum positive `isize` value.
+    /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
+    /// index every address within an object along with one byte past the end, along with allowing
+    /// `isize` to store the difference between any two pointers into an object.
+    ///
+    /// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer
+    /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is
+    /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
+    /// address space on 64-bit ARMv8 and x86_64.
+    #[inline]
+    pub fn obj_size_bound(&self) -> u64 {
+        match self.pointer_size.bits() {
+            16 => 1 << 15,
+            32 => 1 << 31,
+            64 => 1 << 47,
+            bits => panic!("obj_size_bound: unknown pointer bit size {}", bits),
+        }
+    }
+
+    #[inline]
+    pub fn ptr_sized_integer(&self) -> Integer {
+        match self.pointer_size.bits() {
+            16 => I16,
+            32 => I32,
+            64 => I64,
+            bits => panic!("ptr_sized_integer: unknown pointer bit size {}", bits),
+        }
+    }
+
+    #[inline]
+    pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
+        for &(size, align) in &self.vector_align {
+            if size == vec_size {
+                return align;
+            }
+        }
+        // Default to natural alignment, which is what LLVM does.
+        // That is, use the size, rounded up to a power of 2.
+        AbiAndPrefAlign::new(Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap())
+    }
+}
+
+pub trait HasDataLayout {
+    fn data_layout(&self) -> &TargetDataLayout;
+}
+
+impl HasDataLayout for TargetDataLayout {
+    #[inline]
+    fn data_layout(&self) -> &TargetDataLayout {
+        self
+    }
+}
+
+/// Endianness of the target, which must match cfg(target-endian).
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub enum Endian {
+    Little,
+    Big,
+}
+
+impl Endian {
+    pub fn as_str(&self) -> &'static str {
+        match self {
+            Self::Little => "little",
+            Self::Big => "big",
+        }
+    }
+}
+
+impl fmt::Debug for Endian {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(self.as_str())
+    }
+}
+
+impl FromStr for Endian {
+    type Err = String;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "little" => Ok(Self::Little),
+            "big" => Ok(Self::Big),
+            _ => Err(format!(r#"unknown endian: "{}""#, s)),
+        }
+    }
+}
+
+/// Size of a type in bytes.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
+pub struct Size {
+    raw: u64,
+}
+
+// This is debug-printed a lot in larger structs, don't waste too much space there
+impl fmt::Debug for Size {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "Size({} bytes)", self.bytes())
+    }
+}
+
+impl Size {
+    pub const ZERO: Size = Size { raw: 0 };
+
+    /// Rounds `bits` up to the next-higher byte boundary, if `bits` is
+    /// not a multiple of 8.
+    pub fn from_bits(bits: impl TryInto<u64>) -> Size {
+        let bits = bits.try_into().ok().unwrap();
+        // Avoid potential overflow from `bits + 7`.
+        Size { raw: bits / 8 + ((bits % 8) + 7) / 8 }
+    }
+
+    #[inline]
+    pub fn from_bytes(bytes: impl TryInto<u64>) -> Size {
+        let bytes: u64 = bytes.try_into().ok().unwrap();
+        Size { raw: bytes }
+    }
+
+    #[inline]
+    pub fn bytes(self) -> u64 {
+        self.raw
+    }
+
+    #[inline]
+    pub fn bytes_usize(self) -> usize {
+        self.bytes().try_into().unwrap()
+    }
+
+    #[inline]
+    pub fn bits(self) -> u64 {
+        #[cold]
+        fn overflow(bytes: u64) -> ! {
+            panic!("Size::bits: {} bytes in bits doesn't fit in u64", bytes)
+        }
+
+        self.bytes().checked_mul(8).unwrap_or_else(|| overflow(self.bytes()))
+    }
+
+    #[inline]
+    pub fn bits_usize(self) -> usize {
+        self.bits().try_into().unwrap()
+    }
+
+    #[inline]
+    pub fn align_to(self, align: Align) -> Size {
+        let mask = align.bytes() - 1;
+        Size::from_bytes((self.bytes() + mask) & !mask)
+    }
+
+    #[inline]
+    pub fn is_aligned(self, align: Align) -> bool {
+        let mask = align.bytes() - 1;
+        self.bytes() & mask == 0
+    }
+
+    #[inline]
+    pub fn checked_add<C: HasDataLayout>(self, offset: Size, cx: &C) -> Option<Size> {
+        let dl = cx.data_layout();
+
+        let bytes = self.bytes().checked_add(offset.bytes())?;
+
+        if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
+    }
+
+    #[inline]
+    pub fn checked_mul<C: HasDataLayout>(self, count: u64, cx: &C) -> Option<Size> {
+        let dl = cx.data_layout();
+
+        let bytes = self.bytes().checked_mul(count)?;
+        if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
+    }
+
+    /// Truncates `value` to `self` bits and then sign-extends it to 128 bits
+    /// (i.e., if it is negative, fill with 1's on the left).
+    #[inline]
+    pub fn sign_extend(self, value: u128) -> u128 {
+        let size = self.bits();
+        if size == 0 {
+            // Truncated until nothing is left.
+            return 0;
+        }
+        // Sign-extend it.
+        let shift = 128 - size;
+        // Shift the unsigned value to the left, then shift back to the right as signed
+        // (essentially fills with sign bit on the left).
+        (((value << shift) as i128) >> shift) as u128
+    }
+
+    /// Truncates `value` to `self` bits.
+    #[inline]
+    pub fn truncate(self, value: u128) -> u128 {
+        let size = self.bits();
+        if size == 0 {
+            // Truncated until nothing is left.
+            return 0;
+        }
+        let shift = 128 - size;
+        // Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
+        (value << shift) >> shift
+    }
+
+    #[inline]
+    pub fn signed_int_min(&self) -> i128 {
+        self.sign_extend(1_u128 << (self.bits() - 1)) as i128
+    }
+
+    #[inline]
+    pub fn signed_int_max(&self) -> i128 {
+        i128::MAX >> (128 - self.bits())
+    }
+
+    #[inline]
+    pub fn unsigned_int_max(&self) -> u128 {
+        u128::MAX >> (128 - self.bits())
+    }
+}
+
+// Panicking addition, subtraction and multiplication for convenience.
+// Avoid during layout computation, return `LayoutError` instead.
+
+impl Add for Size {
+    type Output = Size;
+    #[inline]
+    fn add(self, other: Size) -> Size {
+        Size::from_bytes(self.bytes().checked_add(other.bytes()).unwrap_or_else(|| {
+            panic!("Size::add: {} + {} doesn't fit in u64", self.bytes(), other.bytes())
+        }))
+    }
+}
+
+impl Sub for Size {
+    type Output = Size;
+    #[inline]
+    fn sub(self, other: Size) -> Size {
+        Size::from_bytes(self.bytes().checked_sub(other.bytes()).unwrap_or_else(|| {
+            panic!("Size::sub: {} - {} would result in negative size", self.bytes(), other.bytes())
+        }))
+    }
+}
+
+impl Mul<Size> for u64 {
+    type Output = Size;
+    #[inline]
+    fn mul(self, size: Size) -> Size {
+        size * self
+    }
+}
+
+impl Mul<u64> for Size {
+    type Output = Size;
+    #[inline]
+    fn mul(self, count: u64) -> Size {
+        match self.bytes().checked_mul(count) {
+            Some(bytes) => Size::from_bytes(bytes),
+            None => panic!("Size::mul: {} * {} doesn't fit in u64", self.bytes(), count),
+        }
+    }
+}
+
+impl AddAssign for Size {
+    #[inline]
+    fn add_assign(&mut self, other: Size) {
+        *self = *self + other;
+    }
+}
+
+#[cfg(feature = "nightly")]
+impl Step for Size {
+    #[inline]
+    fn steps_between(start: &Self, end: &Self) -> Option<usize> {
+        u64::steps_between(&start.bytes(), &end.bytes())
+    }
+
+    #[inline]
+    fn forward_checked(start: Self, count: usize) -> Option<Self> {
+        u64::forward_checked(start.bytes(), count).map(Self::from_bytes)
+    }
+
+    #[inline]
+    fn forward(start: Self, count: usize) -> Self {
+        Self::from_bytes(u64::forward(start.bytes(), count))
+    }
+
+    #[inline]
+    unsafe fn forward_unchecked(start: Self, count: usize) -> Self {
+        Self::from_bytes(u64::forward_unchecked(start.bytes(), count))
+    }
+
+    #[inline]
+    fn backward_checked(start: Self, count: usize) -> Option<Self> {
+        u64::backward_checked(start.bytes(), count).map(Self::from_bytes)
+    }
+
+    #[inline]
+    fn backward(start: Self, count: usize) -> Self {
+        Self::from_bytes(u64::backward(start.bytes(), count))
+    }
+
+    #[inline]
+    unsafe fn backward_unchecked(start: Self, count: usize) -> Self {
+        Self::from_bytes(u64::backward_unchecked(start.bytes(), count))
+    }
+}
+
+/// Alignment of a type in bytes (always a power of two).
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
+pub struct Align {
+    pow2: u8,
+}
+
+// This is debug-printed a lot in larger structs, don't waste too much space there
+impl fmt::Debug for Align {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "Align({} bytes)", self.bytes())
+    }
+}
+
+impl Align {
+    pub const ONE: Align = Align { pow2: 0 };
+    pub const MAX: Align = Align { pow2: 29 };
+
+    #[inline]
+    pub fn from_bits(bits: u64) -> Result<Align, String> {
+        Align::from_bytes(Size::from_bits(bits).bytes())
+    }
+
+    #[inline]
+    pub fn from_bytes(align: u64) -> Result<Align, String> {
+        // Treat an alignment of 0 bytes like 1-byte alignment.
+        if align == 0 {
+            return Ok(Align::ONE);
+        }
+
+        #[cold]
+        fn not_power_of_2(align: u64) -> String {
+            format!("`{}` is not a power of 2", align)
+        }
+
+        #[cold]
+        fn too_large(align: u64) -> String {
+            format!("`{}` is too large", align)
+        }
+
+        let mut bytes = align;
+        let mut pow2: u8 = 0;
+        while (bytes & 1) == 0 {
+            pow2 += 1;
+            bytes >>= 1;
+        }
+        if bytes != 1 {
+            return Err(not_power_of_2(align));
+        }
+        if pow2 > Self::MAX.pow2 {
+            return Err(too_large(align));
+        }
+
+        Ok(Align { pow2 })
+    }
+
+    #[inline]
+    pub fn bytes(self) -> u64 {
+        1 << self.pow2
+    }
+
+    #[inline]
+    pub fn bits(self) -> u64 {
+        self.bytes() * 8
+    }
+
+    /// Computes the best alignment possible for the given offset
+    /// (the largest power of two that the offset is a multiple of).
+    ///
+    /// N.B., for an offset of `0`, this happens to return `2^64`.
+    #[inline]
+    pub fn max_for_offset(offset: Size) -> Align {
+        Align { pow2: offset.bytes().trailing_zeros() as u8 }
+    }
+
+    /// Lower the alignment, if necessary, such that the given offset
+    /// is aligned to it (the offset is a multiple of the alignment).
+    #[inline]
+    pub fn restrict_for_offset(self, offset: Size) -> Align {
+        self.min(Align::max_for_offset(offset))
+    }
+}
+
+/// A pair of alignments, ABI-mandated and preferred.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
+
+pub struct AbiAndPrefAlign {
+    pub abi: Align,
+    pub pref: Align,
+}
+
+impl AbiAndPrefAlign {
+    #[inline]
+    pub fn new(align: Align) -> AbiAndPrefAlign {
+        AbiAndPrefAlign { abi: align, pref: align }
+    }
+
+    #[inline]
+    pub fn min(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
+        AbiAndPrefAlign { abi: self.abi.min(other.abi), pref: self.pref.min(other.pref) }
+    }
+
+    #[inline]
+    pub fn max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
+        AbiAndPrefAlign { abi: self.abi.max(other.abi), pref: self.pref.max(other.pref) }
+    }
+}
+
+/// Integers, also used for enum discriminants.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
+
+pub enum Integer {
+    I8,
+    I16,
+    I32,
+    I64,
+    I128,
+}
+
+impl Integer {
+    #[inline]
+    pub fn size(self) -> Size {
+        match self {
+            I8 => Size::from_bytes(1),
+            I16 => Size::from_bytes(2),
+            I32 => Size::from_bytes(4),
+            I64 => Size::from_bytes(8),
+            I128 => Size::from_bytes(16),
+        }
+    }
+
+    /// Gets the Integer type from an IntegerType.
+    pub fn from_attr<C: HasDataLayout>(cx: &C, ity: IntegerType) -> Integer {
+        let dl = cx.data_layout();
+
+        match ity {
+            IntegerType::Pointer(_) => dl.ptr_sized_integer(),
+            IntegerType::Fixed(x, _) => x,
+        }
+    }
+
+    pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
+        let dl = cx.data_layout();
+
+        match self {
+            I8 => dl.i8_align,
+            I16 => dl.i16_align,
+            I32 => dl.i32_align,
+            I64 => dl.i64_align,
+            I128 => dl.i128_align,
+        }
+    }
+
+    /// Finds the smallest Integer type which can represent the signed value.
+    #[inline]
+    pub fn fit_signed(x: i128) -> Integer {
+        match x {
+            -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8,
+            -0x0000_0000_0000_8000..=0x0000_0000_0000_7fff => I16,
+            -0x0000_0000_8000_0000..=0x0000_0000_7fff_ffff => I32,
+            -0x8000_0000_0000_0000..=0x7fff_ffff_ffff_ffff => I64,
+            _ => I128,
+        }
+    }
+
+    /// Finds the smallest Integer type which can represent the unsigned value.
+    #[inline]
+    pub fn fit_unsigned(x: u128) -> Integer {
+        match x {
+            0..=0x0000_0000_0000_00ff => I8,
+            0..=0x0000_0000_0000_ffff => I16,
+            0..=0x0000_0000_ffff_ffff => I32,
+            0..=0xffff_ffff_ffff_ffff => I64,
+            _ => I128,
+        }
+    }
+
+    /// Finds the smallest integer with the given alignment.
+    pub fn for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer> {
+        let dl = cx.data_layout();
+
+        for candidate in [I8, I16, I32, I64, I128] {
+            if wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() {
+                return Some(candidate);
+            }
+        }
+        None
+    }
+
+    /// Find the largest integer with the given alignment or less.
+    pub fn approximate_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Integer {
+        let dl = cx.data_layout();
+
+        // FIXME(eddyb) maybe include I128 in the future, when it works everywhere.
+        for candidate in [I64, I32, I16] {
+            if wanted >= candidate.align(dl).abi && wanted.bytes() >= candidate.size().bytes() {
+                return candidate;
+            }
+        }
+        I8
+    }
+
+    // FIXME(eddyb) consolidate this and other methods that find the appropriate
+    // `Integer` given some requirements.
+    #[inline]
+    pub fn from_size(size: Size) -> Result<Self, String> {
+        match size.bits() {
+            8 => Ok(Integer::I8),
+            16 => Ok(Integer::I16),
+            32 => Ok(Integer::I32),
+            64 => Ok(Integer::I64),
+            128 => Ok(Integer::I128),
+            _ => Err(format!("rust does not support integers with {} bits", size.bits())),
+        }
+    }
+}
+
+/// Fundamental unit of memory access and layout.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
+pub enum Primitive {
+    /// The `bool` is the signedness of the `Integer` type.
+    ///
+    /// One would think we would not care about such details this low down,
+    /// but some ABIs are described in terms of C types and ISAs where the
+    /// integer arithmetic is done on {sign,zero}-extended registers, e.g.
+    /// a negative integer passed by zero-extension will appear positive in
+    /// the callee, and most operations on it will produce the wrong values.
+    Int(Integer, bool),
+    F32,
+    F64,
+    Pointer,
+}
+
+impl Primitive {
+    pub fn size<C: HasDataLayout>(self, cx: &C) -> Size {
+        let dl = cx.data_layout();
+
+        match self {
+            Int(i, _) => i.size(),
+            F32 => Size::from_bits(32),
+            F64 => Size::from_bits(64),
+            Pointer => dl.pointer_size,
+        }
+    }
+
+    pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
+        let dl = cx.data_layout();
+
+        match self {
+            Int(i, _) => i.align(dl),
+            F32 => dl.f32_align,
+            F64 => dl.f64_align,
+            Pointer => dl.pointer_align,
+        }
+    }
+
+    // FIXME(eddyb) remove, it's trivial thanks to `matches!`.
+    #[inline]
+    pub fn is_float(self) -> bool {
+        matches!(self, F32 | F64)
+    }
+
+    // FIXME(eddyb) remove, it's completely unused.
+    #[inline]
+    pub fn is_int(self) -> bool {
+        matches!(self, Int(..))
+    }
+
+    #[inline]
+    pub fn is_ptr(self) -> bool {
+        matches!(self, Pointer)
+    }
+}
+
+/// Inclusive wrap-around range of valid values, that is, if
+/// start > end, it represents `start..=MAX`,
+/// followed by `0..=end`.
+///
+/// That is, for an i8 primitive, a range of `254..=2` means following
+/// sequence:
+///
+///    254 (-2), 255 (-1), 0, 1, 2
+///
+/// This is intended specifically to mirror LLVM’s `!range` metadata semantics.
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
+pub struct WrappingRange {
+    pub start: u128,
+    pub end: u128,
+}
+
+impl WrappingRange {
+    pub fn full(size: Size) -> Self {
+        Self { start: 0, end: size.unsigned_int_max() }
+    }
+
+    /// Returns `true` if `v` is contained in the range.
+    #[inline(always)]
+    pub fn contains(&self, v: u128) -> bool {
+        if self.start <= self.end {
+            self.start <= v && v <= self.end
+        } else {
+            self.start <= v || v <= self.end
+        }
+    }
+
+    /// Returns `self` with replaced `start`
+    #[inline(always)]
+    pub fn with_start(mut self, start: u128) -> Self {
+        self.start = start;
+        self
+    }
+
+    /// Returns `self` with replaced `end`
+    #[inline(always)]
+    pub fn with_end(mut self, end: u128) -> Self {
+        self.end = end;
+        self
+    }
+
+    /// Returns `true` if `size` completely fills the range.
+    #[inline]
+    pub fn is_full_for(&self, size: Size) -> bool {
+        let max_value = size.unsigned_int_max();
+        debug_assert!(self.start <= max_value && self.end <= max_value);
+        self.start == (self.end.wrapping_add(1) & max_value)
+    }
+}
+
+impl fmt::Debug for WrappingRange {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if self.start > self.end {
+            write!(fmt, "(..={}) | ({}..)", self.end, self.start)?;
+        } else {
+            write!(fmt, "{}..={}", self.start, self.end)?;
+        }
+        Ok(())
+    }
+}
+
+/// Information about one scalar component of a Rust type.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
+pub enum Scalar {
+    Initialized {
+        value: Primitive,
+
+        // FIXME(eddyb) always use the shortest range, e.g., by finding
+        // the largest space between two consecutive valid values and
+        // taking everything else as the (shortest) valid range.
+        valid_range: WrappingRange,
+    },
+    Union {
+        /// Even for unions, we need to use the correct registers for the kind of
+        /// values inside the union, so we keep the `Primitive` type around. We
+        /// also use it to compute the size of the scalar.
+        /// However, unions never have niches and even allow undef,
+        /// so there is no `valid_range`.
+        value: Primitive,
+    },
+}
+
+impl Scalar {
+    #[inline]
+    pub fn is_bool(&self) -> bool {
+        matches!(
+            self,
+            Scalar::Initialized {
+                value: Int(I8, false),
+                valid_range: WrappingRange { start: 0, end: 1 }
+            }
+        )
+    }
+
+    /// Get the primitive representation of this type, ignoring the valid range and whether the
+    /// value is allowed to be undefined (due to being a union).
+    pub fn primitive(&self) -> Primitive {
+        match *self {
+            Scalar::Initialized { value, .. } | Scalar::Union { value } => value,
+        }
+    }
+
+    pub fn align(self, cx: &impl HasDataLayout) -> AbiAndPrefAlign {
+        self.primitive().align(cx)
+    }
+
+    pub fn size(self, cx: &impl HasDataLayout) -> Size {
+        self.primitive().size(cx)
+    }
+
+    #[inline]
+    pub fn to_union(&self) -> Self {
+        Self::Union { value: self.primitive() }
+    }
+
+    #[inline]
+    pub fn valid_range(&self, cx: &impl HasDataLayout) -> WrappingRange {
+        match *self {
+            Scalar::Initialized { valid_range, .. } => valid_range,
+            Scalar::Union { value } => WrappingRange::full(value.size(cx)),
+        }
+    }
+
+    #[inline]
+    /// Allows the caller to mutate the valid range. This operation will panic if attempted on a union.
+    pub fn valid_range_mut(&mut self) -> &mut WrappingRange {
+        match self {
+            Scalar::Initialized { valid_range, .. } => valid_range,
+            Scalar::Union { .. } => panic!("cannot change the valid range of a union"),
+        }
+    }
+
+    /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout
+    #[inline]
+    pub fn is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool {
+        match *self {
+            Scalar::Initialized { valid_range, .. } => valid_range.is_full_for(self.size(cx)),
+            Scalar::Union { .. } => true,
+        }
+    }
+
+    /// Returns `true` if this type can be left uninit.
+    #[inline]
+    pub fn is_uninit_valid(&self) -> bool {
+        match *self {
+            Scalar::Initialized { .. } => false,
+            Scalar::Union { .. } => true,
+        }
+    }
+}
+
+/// Describes how the fields of a type are located in memory.
+#[derive(PartialEq, Eq, Hash, Clone, Debug)]
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
+pub enum FieldsShape {
+    /// Scalar primitives and `!`, which never have fields.
+    Primitive,
+
+    /// All fields start at no offset. The `usize` is the field count.
+    Union(NonZeroUsize),
+
+    /// Array/vector-like placement, with all fields of identical types.
+    Array { stride: Size, count: u64 },
+
+    /// Struct-like placement, with precomputed offsets.
+    ///
+    /// Fields are guaranteed to not overlap, but note that gaps
+    /// before, between and after all the fields are NOT always
+    /// padding, and as such their contents may not be discarded.
+    /// For example, enum variants leave a gap at the start,
+    /// where the discriminant field in the enum layout goes.
+    Arbitrary {
+        /// Offsets for the first byte of each field,
+        /// ordered to match the source definition order.
+        /// This vector does not go in increasing order.
+        // FIXME(eddyb) use small vector optimization for the common case.
+        offsets: Vec<Size>,
+
+        /// Maps source order field indices to memory order indices,
+        /// depending on how the fields were reordered (if at all).
+        /// This is a permutation, with both the source order and the
+        /// memory order using the same (0..n) index ranges.
+        ///
+        /// Note that during computation of `memory_index`, sometimes
+        /// it is easier to operate on the inverse mapping (that is,
+        /// from memory order to source order), and that is usually
+        /// named `inverse_memory_index`.
+        ///
+        // FIXME(eddyb) build a better abstraction for permutations, if possible.
+        // FIXME(camlorn) also consider small vector  optimization here.
+        memory_index: Vec<u32>,
+    },
+}
+
+impl FieldsShape {
+    #[inline]
+    pub fn count(&self) -> usize {
+        match *self {
+            FieldsShape::Primitive => 0,
+            FieldsShape::Union(count) => count.get(),
+            FieldsShape::Array { count, .. } => count.try_into().unwrap(),
+            FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(),
+        }
+    }
+
+    #[inline]
+    pub fn offset(&self, i: usize) -> Size {
+        match *self {
+            FieldsShape::Primitive => {
+                unreachable!("FieldsShape::offset: `Primitive`s have no fields")
+            }
+            FieldsShape::Union(count) => {
+                assert!(
+                    i < count.get(),
+                    "tried to access field {} of union with {} fields",
+                    i,
+                    count
+                );
+                Size::ZERO
+            }
+            FieldsShape::Array { stride, count } => {
+                let i = u64::try_from(i).unwrap();
+                assert!(i < count);
+                stride * i
+            }
+            FieldsShape::Arbitrary { ref offsets, .. } => offsets[i],
+        }
+    }
+
+    #[inline]
+    pub fn memory_index(&self, i: usize) -> usize {
+        match *self {
+            FieldsShape::Primitive => {
+                unreachable!("FieldsShape::memory_index: `Primitive`s have no fields")
+            }
+            FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
+            FieldsShape::Arbitrary { ref memory_index, .. } => memory_index[i].try_into().unwrap(),
+        }
+    }
+
+    /// Gets source indices of the fields by increasing offsets.
+    #[inline]
+    pub fn index_by_increasing_offset<'a>(&'a self) -> impl Iterator<Item = usize> + 'a {
+        let mut inverse_small = [0u8; 64];
+        let mut inverse_big = vec![];
+        let use_small = self.count() <= inverse_small.len();
+
+        // We have to write this logic twice in order to keep the array small.
+        if let FieldsShape::Arbitrary { ref memory_index, .. } = *self {
+            if use_small {
+                for i in 0..self.count() {
+                    inverse_small[memory_index[i] as usize] = i as u8;
+                }
+            } else {
+                inverse_big = vec![0; self.count()];
+                for i in 0..self.count() {
+                    inverse_big[memory_index[i] as usize] = i as u32;
+                }
+            }
+        }
+
+        (0..self.count()).map(move |i| match *self {
+            FieldsShape::Primitive | FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
+            FieldsShape::Arbitrary { .. } => {
+                if use_small {
+                    inverse_small[i] as usize
+                } else {
+                    inverse_big[i] as usize
+                }
+            }
+        })
+    }
+}
+
+/// An identifier that specifies the address space that some operation
+/// should operate on. Special address spaces have an effect on code generation,
+/// depending on the target and the address spaces it implements.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct AddressSpace(pub u32);
+
+impl AddressSpace {
+    /// The default address space, corresponding to data space.
+    pub const DATA: Self = AddressSpace(0);
+}
+
+/// Describes how values of the type are passed by target ABIs,
+/// in terms of categories of C types there are ABI rules for.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
+
+pub enum Abi {
+    Uninhabited,
+    Scalar(Scalar),
+    ScalarPair(Scalar, Scalar),
+    Vector {
+        element: Scalar,
+        count: u64,
+    },
+    Aggregate {
+        /// If true, the size is exact, otherwise it's only a lower bound.
+        sized: bool,
+    },
+}
+
+impl Abi {
+    /// Returns `true` if the layout corresponds to an unsized type.
+    #[inline]
+    pub fn is_unsized(&self) -> bool {
+        match *self {
+            Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
+            Abi::Aggregate { sized } => !sized,
+        }
+    }
+
+    #[inline]
+    pub fn is_sized(&self) -> bool {
+        !self.is_unsized()
+    }
+
+    /// Returns `true` if this is a single signed integer scalar
+    #[inline]
+    pub fn is_signed(&self) -> bool {
+        match self {
+            Abi::Scalar(scal) => match scal.primitive() {
+                Primitive::Int(_, signed) => signed,
+                _ => false,
+            },
+            _ => panic!("`is_signed` on non-scalar ABI {:?}", self),
+        }
+    }
+
+    /// Returns `true` if this is an uninhabited type
+    #[inline]
+    pub fn is_uninhabited(&self) -> bool {
+        matches!(*self, Abi::Uninhabited)
+    }
+
+    /// Returns `true` is this is a scalar type
+    #[inline]
+    pub fn is_scalar(&self) -> bool {
+        matches!(*self, Abi::Scalar(_))
+    }
+}
+
+#[derive(PartialEq, Eq, Hash, Clone, Debug)]
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
+pub enum Variants<V: Idx> {
+    /// Single enum variants, structs/tuples, unions, and all non-ADTs.
+    Single { index: V },
+
+    /// Enum-likes with more than one inhabited variant: each variant comes with
+    /// a *discriminant* (usually the same as the variant index but the user can
+    /// assign explicit discriminant values).  That discriminant is encoded
+    /// as a *tag* on the machine.  The layout of each variant is
+    /// a struct, and they all have space reserved for the tag.
+    /// For enums, the tag is the sole field of the layout.
+    Multiple {
+        tag: Scalar,
+        tag_encoding: TagEncoding<V>,
+        tag_field: usize,
+        variants: IndexVec<V, LayoutS<V>>,
+    },
+}
+
+#[derive(PartialEq, Eq, Hash, Clone, Debug)]
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
+pub enum TagEncoding<V: Idx> {
+    /// The tag directly stores the discriminant, but possibly with a smaller layout
+    /// (so converting the tag to the discriminant can require sign extension).
+    Direct,
+
+    /// Niche (values invalid for a type) encoding the discriminant:
+    /// Discriminant and variant index coincide.
+    /// The variant `untagged_variant` contains a niche at an arbitrary
+    /// offset (field `tag_field` of the enum), which for a variant with
+    /// discriminant `d` is set to
+    /// `(d - niche_variants.start).wrapping_add(niche_start)`.
+    ///
+    /// For example, `Option<(usize, &T)>`  is represented such that
+    /// `None` has a null pointer for the second tuple field, and
+    /// `Some` is the identity function (with a non-null reference).
+    Niche { untagged_variant: V, niche_variants: RangeInclusive<V>, niche_start: u128 },
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
+pub struct Niche {
+    pub offset: Size,
+    pub value: Primitive,
+    pub valid_range: WrappingRange,
+}
+
+impl Niche {
+    pub fn from_scalar<C: HasDataLayout>(cx: &C, offset: Size, scalar: Scalar) -> Option<Self> {
+        let Scalar::Initialized { value, valid_range } = scalar else { return None };
+        let niche = Niche { offset, value, valid_range };
+        if niche.available(cx) > 0 { Some(niche) } else { None }
+    }
+
+    pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
+        let Self { value, valid_range: v, .. } = *self;
+        let size = value.size(cx);
+        assert!(size.bits() <= 128);
+        let max_value = size.unsigned_int_max();
+
+        // Find out how many values are outside the valid range.
+        let niche = v.end.wrapping_add(1)..v.start;
+        niche.end.wrapping_sub(niche.start) & max_value
+    }
+
+    pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
+        assert!(count > 0);
+
+        let Self { value, valid_range: v, .. } = *self;
+        let size = value.size(cx);
+        assert!(size.bits() <= 128);
+        let max_value = size.unsigned_int_max();
+
+        let niche = v.end.wrapping_add(1)..v.start;
+        let available = niche.end.wrapping_sub(niche.start) & max_value;
+        if count > available {
+            return None;
+        }
+
+        // Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound.
+        // Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy the niche of zero.
+        // This is accomplished by preferring enums with 2 variants(`count==1`) and always taking the shortest path to niche zero.
+        // Having `None` in niche zero can enable some special optimizations.
+        //
+        // Bound selection criteria:
+        // 1. Select closest to zero given wrapping semantics.
+        // 2. Avoid moving past zero if possible.
+        //
+        // In practice this means that enums with `count > 1` are unlikely to claim niche zero, since they have to fit perfectly.
+        // If niche zero is already reserved, the selection of bounds are of little interest.
+        let move_start = |v: WrappingRange| {
+            let start = v.start.wrapping_sub(count) & max_value;
+            Some((start, Scalar::Initialized { value, valid_range: v.with_start(start) }))
+        };
+        let move_end = |v: WrappingRange| {
+            let start = v.end.wrapping_add(1) & max_value;
+            let end = v.end.wrapping_add(count) & max_value;
+            Some((start, Scalar::Initialized { value, valid_range: v.with_end(end) }))
+        };
+        let distance_end_zero = max_value - v.end;
+        if v.start > v.end {
+            // zero is unavailable because wrapping occurs
+            move_end(v)
+        } else if v.start <= distance_end_zero {
+            if count <= v.start {
+                move_start(v)
+            } else {
+                // moved past zero, use other bound
+                move_end(v)
+            }
+        } else {
+            let end = v.end.wrapping_add(count) & max_value;
+            let overshot_zero = (1..=v.end).contains(&end);
+            if overshot_zero {
+                // moved past zero, use other bound
+                move_start(v)
+            } else {
+                move_end(v)
+            }
+        }
+    }
+}
+
+#[derive(PartialEq, Eq, Hash, Clone)]
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
+pub struct LayoutS<V: Idx> {
+    /// Says where the fields are located within the layout.
+    pub fields: FieldsShape,
+
+    /// Encodes information about multi-variant layouts.
+    /// Even with `Multiple` variants, a layout still has its own fields! Those are then
+    /// shared between all variants. One of them will be the discriminant,
+    /// but e.g. generators can have more.
+    ///
+    /// To access all fields of this layout, both `fields` and the fields of the active variant
+    /// must be taken into account.
+    pub variants: Variants<V>,
+
+    /// The `abi` defines how this data is passed between functions, and it defines
+    /// value restrictions via `valid_range`.
+    ///
+    /// Note that this is entirely orthogonal to the recursive structure defined by
+    /// `variants` and `fields`; for example, `ManuallyDrop<Result<isize, isize>>` has
+    /// `Abi::ScalarPair`! So, even with non-`Aggregate` `abi`, `fields` and `variants`
+    /// have to be taken into account to find all fields of this layout.
+    pub abi: Abi,
+
+    /// The leaf scalar with the largest number of invalid values
+    /// (i.e. outside of its `valid_range`), if it exists.
+    pub largest_niche: Option<Niche>,
+
+    pub align: AbiAndPrefAlign,
+    pub size: Size,
+}
+
+impl<V: Idx> LayoutS<V> {
+    pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
+        let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
+        let size = scalar.size(cx);
+        let align = scalar.align(cx);
+        LayoutS {
+            variants: Variants::Single { index: V::new(0) },
+            fields: FieldsShape::Primitive,
+            abi: Abi::Scalar(scalar),
+            largest_niche,
+            size,
+            align,
+        }
+    }
+}
+
+impl<V: Idx> fmt::Debug for LayoutS<V> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // This is how `Layout` used to print before it become
+        // `Interned<LayoutS>`. We print it like this to avoid having to update
+        // expected output in a lot of tests.
+        let LayoutS { size, align, abi, fields, largest_niche, variants } = self;
+        f.debug_struct("Layout")
+            .field("size", size)
+            .field("align", align)
+            .field("abi", abi)
+            .field("fields", fields)
+            .field("largest_niche", largest_niche)
+            .field("variants", variants)
+            .finish()
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum PointerKind {
+    /// Most general case, we know no restrictions to tell LLVM.
+    SharedMutable,
+
+    /// `&T` where `T` contains no `UnsafeCell`, is `dereferenceable`, `noalias` and `readonly`.
+    Frozen,
+
+    /// `&mut T` which is `dereferenceable` and `noalias` but not `readonly`.
+    UniqueBorrowed,
+
+    /// `&mut !Unpin`, which is `dereferenceable` but neither `noalias` nor `readonly`.
+    UniqueBorrowedPinned,
+
+    /// `Box<T>`, which is `noalias` (even on return types, unlike the above) but neither `readonly`
+    /// nor `dereferenceable`.
+    UniqueOwned,
+}
+
+#[derive(Copy, Clone, Debug)]
+pub struct PointeeInfo {
+    pub size: Size,
+    pub align: Align,
+    pub safe: Option<PointerKind>,
+    pub address_space: AddressSpace,
+}
+
+/// Used in `might_permit_raw_init` to indicate the kind of initialisation
+/// that is checked to be valid
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum InitKind {
+    Zero,
+    UninitMitigated0x01Fill,
+}
+
+impl<V: Idx> LayoutS<V> {
+    /// Returns `true` if the layout corresponds to an unsized type.
+    pub fn is_unsized(&self) -> bool {
+        self.abi.is_unsized()
+    }
+
+    pub fn is_sized(&self) -> bool {
+        self.abi.is_sized()
+    }
+
+    /// Returns `true` if the type is a ZST and not unsized.
+    pub fn is_zst(&self) -> bool {
+        match self.abi {
+            Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
+            Abi::Uninhabited => self.size.bytes() == 0,
+            Abi::Aggregate { sized } => sized && self.size.bytes() == 0,
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug)]
+pub enum StructKind {
+    /// A tuple, closure, or univariant which cannot be coerced to unsized.
+    AlwaysSized,
+    /// A univariant, the last field of which may be coerced to unsized.
+    MaybeUnsized,
+    /// A univariant, but with a prefix of an arbitrary size & alignment (e.g., enum tag).
+    Prefixed(Size, Align),
+}
diff --git a/compiler/rustc_arena/src/tests.rs b/compiler/rustc_arena/src/tests.rs
index ad61464343a..49a070badc6 100644
--- a/compiler/rustc_arena/src/tests.rs
+++ b/compiler/rustc_arena/src/tests.rs
@@ -52,19 +52,15 @@ fn test_arena_alloc_nested() {
 
     impl<'a> Wrap<'a> {
         fn alloc_inner<F: Fn() -> Inner>(&self, f: F) -> &Inner {
-            let r: &EI<'_> = self.0.alloc(EI::I(f()));
-            if let &EI::I(ref i) = r {
-                i
-            } else {
-                panic!("mismatch");
+            match self.0.alloc(EI::I(f())) {
+                EI::I(i) => i,
+                _ => panic!("mismatch"),
             }
         }
         fn alloc_outer<F: Fn() -> Outer<'a>>(&self, f: F) -> &Outer<'_> {
-            let r: &EI<'_> = self.0.alloc(EI::O(f()));
-            if let &EI::O(ref o) = r {
-                o
-            } else {
-                panic!("mismatch");
+            match self.0.alloc(EI::O(f())) {
+                EI::O(o) => o,
+                _ => panic!("mismatch"),
             }
         }
     }
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index fa745a8e08b..28072f153a4 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1376,7 +1376,7 @@ pub enum ExprKind {
     /// Conditionless loop (can be exited with `break`, `continue`, or `return`).
     ///
     /// `'label: loop { block }`
-    Loop(P<Block>, Option<Label>),
+    Loop(P<Block>, Option<Label>, Span),
     /// A `match` block.
     Match(P<Expr>, Vec<Arm>),
     /// A closure (e.g., `move |a, b, c| a + b + c`).
@@ -2675,7 +2675,7 @@ impl VariantData {
     }
 
     /// Return the `NodeId` of this variant's constructor, if it has one.
-    pub fn ctor_id(&self) -> Option<NodeId> {
+    pub fn ctor_node_id(&self) -> Option<NodeId> {
         match *self {
             VariantData::Struct(..) => None,
             VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id),
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 2f7c7a29492..3e012953115 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -618,9 +618,12 @@ impl MetaItemKind {
             }) => MetaItemKind::list_from_tokens(tokens.clone()),
             AttrArgs::Delimited(..) => None,
             AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind {
-                ast::ExprKind::Lit(token_lit) => Some(MetaItemKind::NameValue(
-                    Lit::from_token_lit(token_lit, expr.span).expect("token_lit in from_attr_args"),
-                )),
+                ast::ExprKind::Lit(token_lit) => {
+                    // Turn failures to `None`, we'll get parse errors elsewhere.
+                    Lit::from_token_lit(token_lit, expr.span)
+                        .ok()
+                        .map(|lit| MetaItemKind::NameValue(lit))
+                }
                 _ => None,
             },
             AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => Some(MetaItemKind::NameValue(lit.clone())),
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 4e1dcb2842f..a5b24c403dd 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1355,9 +1355,10 @@ pub fn noop_visit_expr<T: MutVisitor>(
             vis.visit_block(body);
             visit_opt(label, |label| vis.visit_label(label));
         }
-        ExprKind::Loop(body, label) => {
+        ExprKind::Loop(body, label, span) => {
             vis.visit_block(body);
             visit_opt(label, |label| vis.visit_label(label));
+            vis.visit_span(span);
         }
         ExprKind::Match(expr, arms) => {
             vis.visit_expr(expr);
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 5c69e535212..c528118be08 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -824,7 +824,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
             visitor.visit_expr(subexpression);
             visitor.visit_block(block);
         }
-        ExprKind::Loop(block, opt_label) => {
+        ExprKind::Loop(block, opt_label, _) => {
             walk_list!(visitor, visit_label, opt_label);
             visitor.visit_block(block);
         }
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index db0d8b08a94..2a0338adc9c 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -123,7 +123,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             .operands
             .iter()
             .map(|(op, op_sp)| {
-                let lower_reg = |reg| match reg {
+                let lower_reg = |&reg: &_| match reg {
                     InlineAsmRegOrRegClass::Reg(reg) => {
                         asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch {
                             asm::InlineAsmReg::parse(asm_arch, reg).unwrap_or_else(|error| {
@@ -152,32 +152,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     }
                 };
 
-                let op = match *op {
-                    InlineAsmOperand::In { reg, ref expr } => hir::InlineAsmOperand::In {
+                let op = match op {
+                    InlineAsmOperand::In { reg, expr } => hir::InlineAsmOperand::In {
                         reg: lower_reg(reg),
                         expr: self.lower_expr(expr),
                     },
-                    InlineAsmOperand::Out { reg, late, ref expr } => hir::InlineAsmOperand::Out {
+                    InlineAsmOperand::Out { reg, late, expr } => hir::InlineAsmOperand::Out {
                         reg: lower_reg(reg),
-                        late,
+                        late: *late,
                         expr: expr.as_ref().map(|expr| self.lower_expr(expr)),
                     },
-                    InlineAsmOperand::InOut { reg, late, ref expr } => {
-                        hir::InlineAsmOperand::InOut {
-                            reg: lower_reg(reg),
-                            late,
-                            expr: self.lower_expr(expr),
-                        }
-                    }
-                    InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => {
+                    InlineAsmOperand::InOut { reg, late, expr } => hir::InlineAsmOperand::InOut {
+                        reg: lower_reg(reg),
+                        late: *late,
+                        expr: self.lower_expr(expr),
+                    },
+                    InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
                         hir::InlineAsmOperand::SplitInOut {
                             reg: lower_reg(reg),
-                            late,
+                            late: *late,
                             in_expr: self.lower_expr(in_expr),
                             out_expr: out_expr.as_ref().map(|expr| self.lower_expr(expr)),
                         }
                     }
-                    InlineAsmOperand::Const { ref anon_const } => {
+                    InlineAsmOperand::Const { anon_const } => {
                         if !self.tcx.features().asm_const {
                             feature_err(
                                 &sess.parse_sess,
@@ -191,7 +189,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             anon_const: self.lower_anon_const(anon_const),
                         }
                     }
-                    InlineAsmOperand::Sym { ref sym } => {
+                    InlineAsmOperand::Sym { sym } => {
                         let static_def_id = self
                             .resolver
                             .get_partial_res(sym.id)
@@ -347,7 +345,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                     skip = true;
 
                                     let idx2 = *o.get();
-                                    let &(ref op2, op_sp2) = &operands[idx2];
+                                    let (ref op2, op_sp2) = operands[idx2];
                                     let Some(asm::InlineAsmRegOrRegClass::Reg(reg2)) = op2.reg() else {
                                         unreachable!();
                                     };
diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs
index 12a0cc0d255..d310f72f7a3 100644
--- a/compiler/rustc_ast_lowering/src/block.rs
+++ b/compiler/rustc_ast_lowering/src/block.rs
@@ -31,8 +31,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let mut stmts = SmallVec::<[hir::Stmt<'hir>; 8]>::new();
         let mut expr = None;
         while let [s, tail @ ..] = ast_stmts {
-            match s.kind {
-                StmtKind::Local(ref local) => {
+            match &s.kind {
+                StmtKind::Local(local) => {
                     let hir_id = self.lower_node_id(s.id);
                     let local = self.lower_local(local);
                     self.alias_attrs(hir_id, local.hir_id);
@@ -40,7 +40,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     let span = self.lower_span(s.span);
                     stmts.push(hir::Stmt { hir_id, kind, span });
                 }
-                StmtKind::Item(ref it) => {
+                StmtKind::Item(it) => {
                     stmts.extend(self.lower_item_ref(it).into_iter().enumerate().map(
                         |(i, item_id)| {
                             let hir_id = match i {
@@ -53,7 +53,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         },
                     ));
                 }
-                StmtKind::Expr(ref e) => {
+                StmtKind::Expr(e) => {
                     let e = self.lower_expr(e);
                     if tail.is_empty() {
                         expr = Some(e);
@@ -65,7 +65,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         stmts.push(hir::Stmt { hir_id, kind, span });
                     }
                 }
-                StmtKind::Semi(ref e) => {
+                StmtKind::Semi(e) => {
                     let e = self.lower_expr(e);
                     let hir_id = self.lower_node_id(s.id);
                     self.alias_attrs(hir_id, e.hir_id);
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 3ab42497d6d..23a38a092d9 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -31,20 +31,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
         ensure_sufficient_stack(|| {
-            let kind = match e.kind {
-                ExprKind::Box(ref inner) => hir::ExprKind::Box(self.lower_expr(inner)),
-                ExprKind::Array(ref exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
-                ExprKind::ConstBlock(ref anon_const) => {
+            let kind = match &e.kind {
+                ExprKind::Box(inner) => hir::ExprKind::Box(self.lower_expr(inner)),
+                ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
+                ExprKind::ConstBlock(anon_const) => {
                     let anon_const = self.lower_anon_const(anon_const);
                     hir::ExprKind::ConstBlock(anon_const)
                 }
-                ExprKind::Repeat(ref expr, ref count) => {
+                ExprKind::Repeat(expr, count) => {
                     let expr = self.lower_expr(expr);
                     let count = self.lower_array_length(count);
                     hir::ExprKind::Repeat(expr, count)
                 }
-                ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
-                ExprKind::Call(ref f, ref args) => {
+                ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
+                ExprKind::Call(f, args) => {
                     if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) {
                         if let [inner] = &args[..] && e.attrs.len() == 1 {
                             let kind = hir::ExprKind::Box(self.lower_expr(&inner));
@@ -61,7 +61,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         hir::ExprKind::Call(f, self.lower_exprs(args))
                     }
                 }
-                ExprKind::MethodCall(box MethodCall { ref seg, ref receiver, ref args, span }) => {
+                ExprKind::MethodCall(box MethodCall { seg, receiver, args, span }) => {
                     let hir_seg = self.arena.alloc(self.lower_path_segment(
                         e.span,
                         seg,
@@ -72,92 +72,88 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let receiver = self.lower_expr(receiver);
                     let args =
                         self.arena.alloc_from_iter(args.iter().map(|x| self.lower_expr_mut(x)));
-                    hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(span))
+                    hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(*span))
                 }
-                ExprKind::Binary(binop, ref lhs, ref rhs) => {
-                    let binop = self.lower_binop(binop);
+                ExprKind::Binary(binop, lhs, rhs) => {
+                    let binop = self.lower_binop(*binop);
                     let lhs = self.lower_expr(lhs);
                     let rhs = self.lower_expr(rhs);
                     hir::ExprKind::Binary(binop, lhs, rhs)
                 }
-                ExprKind::Unary(op, ref ohs) => {
-                    let op = self.lower_unop(op);
+                ExprKind::Unary(op, ohs) => {
+                    let op = self.lower_unop(*op);
                     let ohs = self.lower_expr(ohs);
                     hir::ExprKind::Unary(op, ohs)
                 }
                 ExprKind::Lit(token_lit) => {
-                    let lit_kind = match LitKind::from_token_lit(token_lit) {
+                    let lit_kind = match LitKind::from_token_lit(*token_lit) {
                         Ok(lit_kind) => lit_kind,
                         Err(err) => {
-                            report_lit_error(&self.tcx.sess.parse_sess, err, token_lit, e.span);
+                            report_lit_error(&self.tcx.sess.parse_sess, err, *token_lit, e.span);
                             LitKind::Err
                         }
                     };
                     hir::ExprKind::Lit(respan(self.lower_span(e.span), lit_kind))
                 }
-                ExprKind::IncludedBytes(ref bytes) => hir::ExprKind::Lit(respan(
+                ExprKind::IncludedBytes(bytes) => hir::ExprKind::Lit(respan(
                     self.lower_span(e.span),
                     LitKind::ByteStr(bytes.clone()),
                 )),
-                ExprKind::Cast(ref expr, ref ty) => {
+                ExprKind::Cast(expr, ty) => {
                     let expr = self.lower_expr(expr);
                     let ty =
                         self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
                     hir::ExprKind::Cast(expr, ty)
                 }
-                ExprKind::Type(ref expr, ref ty) => {
+                ExprKind::Type(expr, ty) => {
                     let expr = self.lower_expr(expr);
                     let ty =
                         self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
                     hir::ExprKind::Type(expr, ty)
                 }
-                ExprKind::AddrOf(k, m, ref ohs) => {
+                ExprKind::AddrOf(k, m, ohs) => {
                     let ohs = self.lower_expr(ohs);
-                    hir::ExprKind::AddrOf(k, m, ohs)
+                    hir::ExprKind::AddrOf(*k, *m, ohs)
                 }
-                ExprKind::Let(ref pat, ref scrutinee, span) => {
+                ExprKind::Let(pat, scrutinee, span) => {
                     hir::ExprKind::Let(self.arena.alloc(hir::Let {
                         hir_id: self.next_id(),
-                        span: self.lower_span(span),
+                        span: self.lower_span(*span),
                         pat: self.lower_pat(pat),
                         ty: None,
                         init: self.lower_expr(scrutinee),
                     }))
                 }
-                ExprKind::If(ref cond, ref then, ref else_opt) => {
+                ExprKind::If(cond, then, else_opt) => {
                     self.lower_expr_if(cond, then, else_opt.as_deref())
                 }
-                ExprKind::While(ref cond, ref body, opt_label) => {
-                    self.with_loop_scope(e.id, |this| {
-                        let span =
-                            this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None);
-                        this.lower_expr_while_in_loop_scope(span, cond, body, opt_label)
-                    })
-                }
-                ExprKind::Loop(ref body, opt_label) => self.with_loop_scope(e.id, |this| {
+                ExprKind::While(cond, body, opt_label) => self.with_loop_scope(e.id, |this| {
+                    let span = this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None);
+                    this.lower_expr_while_in_loop_scope(span, cond, body, *opt_label)
+                }),
+                ExprKind::Loop(body, opt_label, span) => self.with_loop_scope(e.id, |this| {
                     hir::ExprKind::Loop(
                         this.lower_block(body, false),
-                        this.lower_label(opt_label),
+                        this.lower_label(*opt_label),
                         hir::LoopSource::Loop,
-                        DUMMY_SP,
+                        this.lower_span(*span),
                     )
                 }),
-                ExprKind::TryBlock(ref body) => self.lower_expr_try_block(body),
-                ExprKind::Match(ref expr, ref arms) => hir::ExprKind::Match(
+                ExprKind::TryBlock(body) => self.lower_expr_try_block(body),
+                ExprKind::Match(expr, arms) => hir::ExprKind::Match(
                     self.lower_expr(expr),
                     self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
                     hir::MatchSource::Normal,
                 ),
-                ExprKind::Async(capture_clause, closure_node_id, ref block) => self
-                    .make_async_expr(
-                        capture_clause,
-                        closure_node_id,
-                        None,
-                        block.span,
-                        hir::AsyncGeneratorKind::Block,
-                        |this| this.with_new_scopes(|this| this.lower_block_expr(block)),
-                    ),
-                ExprKind::Await(ref expr) => {
+                ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr(
+                    *capture_clause,
+                    *closure_node_id,
+                    None,
+                    e.span,
+                    hir::AsyncGeneratorKind::Block,
+                    |this| this.with_new_scopes(|this| this.lower_block_expr(block)),
+                ),
+                ExprKind::Await(expr) => {
                     let dot_await_span = if expr.span.hi() < e.span.hi() {
                         let span_with_whitespace = self
                             .tcx
@@ -173,65 +169,63 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     self.lower_expr_await(dot_await_span, expr)
                 }
                 ExprKind::Closure(box Closure {
-                    ref binder,
+                    binder,
                     capture_clause,
                     asyncness,
                     movability,
-                    ref fn_decl,
-                    ref body,
+                    fn_decl,
+                    body,
                     fn_decl_span,
                 }) => {
                     if let Async::Yes { closure_id, .. } = asyncness {
                         self.lower_expr_async_closure(
                             binder,
-                            capture_clause,
+                            *capture_clause,
                             e.id,
-                            closure_id,
+                            *closure_id,
                             fn_decl,
                             body,
-                            fn_decl_span,
+                            *fn_decl_span,
                         )
                     } else {
                         self.lower_expr_closure(
                             binder,
-                            capture_clause,
+                            *capture_clause,
                             e.id,
-                            movability,
+                            *movability,
                             fn_decl,
                             body,
-                            fn_decl_span,
+                            *fn_decl_span,
                         )
                     }
                 }
-                ExprKind::Block(ref blk, opt_label) => {
-                    let opt_label = self.lower_label(opt_label);
+                ExprKind::Block(blk, opt_label) => {
+                    let opt_label = self.lower_label(*opt_label);
                     hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label)
                 }
-                ExprKind::Assign(ref el, ref er, span) => {
-                    self.lower_expr_assign(el, er, span, e.span)
-                }
-                ExprKind::AssignOp(op, ref el, ref er) => hir::ExprKind::AssignOp(
-                    self.lower_binop(op),
+                ExprKind::Assign(el, er, span) => self.lower_expr_assign(el, er, *span, e.span),
+                ExprKind::AssignOp(op, el, er) => hir::ExprKind::AssignOp(
+                    self.lower_binop(*op),
                     self.lower_expr(el),
                     self.lower_expr(er),
                 ),
-                ExprKind::Field(ref el, ident) => {
-                    hir::ExprKind::Field(self.lower_expr(el), self.lower_ident(ident))
+                ExprKind::Field(el, ident) => {
+                    hir::ExprKind::Field(self.lower_expr(el), self.lower_ident(*ident))
                 }
-                ExprKind::Index(ref el, ref er) => {
+                ExprKind::Index(el, er) => {
                     hir::ExprKind::Index(self.lower_expr(el), self.lower_expr(er))
                 }
-                ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => {
+                ExprKind::Range(Some(e1), Some(e2), RangeLimits::Closed) => {
                     self.lower_expr_range_closed(e.span, e1, e2)
                 }
-                ExprKind::Range(ref e1, ref e2, lims) => {
-                    self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), lims)
+                ExprKind::Range(e1, e2, lims) => {
+                    self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims)
                 }
                 ExprKind::Underscore => {
                     self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span });
                     hir::ExprKind::Err
                 }
-                ExprKind::Path(ref qself, ref path) => {
+                ExprKind::Path(qself, path) => {
                     let qpath = self.lower_qpath(
                         e.id,
                         qself,
@@ -241,22 +235,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     );
                     hir::ExprKind::Path(qpath)
                 }
-                ExprKind::Break(opt_label, ref opt_expr) => {
+                ExprKind::Break(opt_label, opt_expr) => {
                     let opt_expr = opt_expr.as_ref().map(|x| self.lower_expr(x));
-                    hir::ExprKind::Break(self.lower_jump_destination(e.id, opt_label), opt_expr)
+                    hir::ExprKind::Break(self.lower_jump_destination(e.id, *opt_label), opt_expr)
                 }
                 ExprKind::Continue(opt_label) => {
-                    hir::ExprKind::Continue(self.lower_jump_destination(e.id, opt_label))
+                    hir::ExprKind::Continue(self.lower_jump_destination(e.id, *opt_label))
                 }
-                ExprKind::Ret(ref e) => {
+                ExprKind::Ret(e) => {
                     let e = e.as_ref().map(|x| self.lower_expr(x));
                     hir::ExprKind::Ret(e)
                 }
-                ExprKind::Yeet(ref sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()),
-                ExprKind::InlineAsm(ref asm) => {
+                ExprKind::Yeet(sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()),
+                ExprKind::InlineAsm(asm) => {
                     hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))
                 }
-                ExprKind::Struct(ref se) => {
+                ExprKind::Struct(se) => {
                     let rest = match &se.rest {
                         StructRest::Base(e) => Some(self.lower_expr(e)),
                         StructRest::Rest(sp) => {
@@ -278,10 +272,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         rest,
                     )
                 }
-                ExprKind::Yield(ref opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
+                ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
                 ExprKind::Err => hir::ExprKind::Err,
-                ExprKind::Try(ref sub_expr) => self.lower_expr_try(e.span, sub_expr),
-                ExprKind::Paren(ref ex) => {
+                ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
+                ExprKind::Paren(ex) => {
                     let mut ex = self.lower_expr_mut(ex);
                     // Include parens in span, but only if it is a super-span.
                     if e.span.contains(ex.span) {
@@ -306,8 +300,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
                 // Desugar `ExprForLoop`
                 // from: `[opt_ident]: for <pat> in <head> <body>`
-                ExprKind::ForLoop(ref pat, ref head, ref body, opt_label) => {
-                    return self.lower_expr_for(e, pat, head, body, opt_label);
+                ExprKind::ForLoop(pat, head, body, opt_label) => {
+                    return self.lower_expr_for(e, pat, head, body, *opt_label);
                 }
                 ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
             };
@@ -358,7 +352,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         args: Vec<AstP<Expr>>,
         legacy_args_idx: &[usize],
     ) -> hir::ExprKind<'hir> {
-        let ExprKind::Path(None, ref mut path) = f.kind else {
+        let ExprKind::Path(None, path) = &mut f.kind else {
             unreachable!();
         };
 
@@ -552,10 +546,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
         let pat = self.lower_pat(&arm.pat);
         let guard = arm.guard.as_ref().map(|cond| {
-            if let ExprKind::Let(ref pat, ref scrutinee, span) = cond.kind {
+            if let ExprKind::Let(pat, scrutinee, span) = &cond.kind {
                 hir::Guard::IfLet(self.arena.alloc(hir::Let {
                     hir_id: self.next_id(),
-                    span: self.lower_span(span),
+                    span: self.lower_span(*span),
                     pat: self.lower_pat(pat),
                     ty: None,
                     init: self.lower_expr(scrutinee),
@@ -575,12 +569,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
-    /// Lower an `async` construct to a generator that is then wrapped so it implements `Future`.
+    /// Lower an `async` construct to a generator that implements `Future`.
     ///
     /// This results in:
     ///
     /// ```text
-    /// std::future::from_generator(static move? |_task_context| -> <ret_ty> {
+    /// std::future::identity_future(static move? |_task_context| -> <ret_ty> {
     ///     <body>
     /// })
     /// ```
@@ -588,24 +582,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
         &mut self,
         capture_clause: CaptureBy,
         closure_node_id: NodeId,
-        ret_ty: Option<AstP<Ty>>,
+        ret_ty: Option<hir::FnRetTy<'hir>>,
         span: Span,
         async_gen_kind: hir::AsyncGeneratorKind,
         body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
     ) -> hir::ExprKind<'hir> {
-        let output = match ret_ty {
-            Some(ty) => hir::FnRetTy::Return(
-                self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock)),
-            ),
-            None => hir::FnRetTy::DefaultReturn(self.lower_span(span)),
-        };
+        let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
 
-        // Resume argument type. We let the compiler infer this to simplify the lowering. It is
-        // fully constrained by `future::from_generator`.
+        // Resume argument type: `ResumeTy`
+        let unstable_span =
+            self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
+        let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span, None);
         let input_ty = hir::Ty {
             hir_id: self.next_id(),
-            kind: hir::TyKind::Infer,
-            span: self.lower_span(span),
+            kind: hir::TyKind::Path(resume_ty),
+            span: unstable_span,
         };
 
         // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
@@ -688,16 +679,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         let generator = hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) };
 
-        // `future::from_generator`:
-        let gen_future = self.expr_lang_item_path(
+        // FIXME(swatinem):
+        // For some reason, the async block needs to flow through *any*
+        // call (like the identity function), as otherwise type and lifetime
+        // inference have a hard time figuring things out.
+        // Without this, we would get:
+        // E0720 in src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs
+        // E0700 in src/test/ui/self/self_lifetime-async.rs
+
+        // `future::identity_future`:
+        let identity_future = self.expr_lang_item_path(
             unstable_span,
-            hir::LangItem::FromGenerator,
+            hir::LangItem::IdentityFuture,
             AttrVec::new(),
             None,
         );
 
-        // `future::from_generator(generator)`:
-        hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator])
+        // `future::identity_future(generator)`:
+        hir::ExprKind::Call(self.arena.alloc(identity_future), arena_vec![self; generator])
     }
 
     /// Desugar `<expr>.await` into:
@@ -966,8 +965,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
     ) -> (hir::ClosureBinder, &'c [GenericParam]) {
         let (binder, params) = match binder {
             ClosureBinder::NotPresent => (hir::ClosureBinder::Default, &[][..]),
-            &ClosureBinder::For { span, ref generic_params } => {
-                let span = self.lower_span(span);
+            ClosureBinder::For { span, generic_params } => {
+                let span = self.lower_span(*span);
                 (hir::ClosureBinder::For { span }, &**generic_params)
             }
         };
@@ -1001,10 +1000,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
 
             // Transform `async |x: u8| -> X { ... }` into
-            // `|x: u8| future_from_generator(|| -> X { ... })`.
+            // `|x: u8| identity_future(|| -> X { ... })`.
             let body_id = this.lower_fn_body(&outer_decl, |this| {
-                let async_ret_ty =
-                    if let FnRetTy::Ty(ty) = &decl.output { Some(ty.clone()) } else { None };
+                let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output {
+                    let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock);
+                    Some(hir::FnRetTy::Return(this.lower_ty(&ty, &itctx)))
+                } else {
+                    None
+                };
+
                 let async_body = this.make_async_expr(
                     capture_clause,
                     inner_closure_id,
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index 3a0e5f55ec1..695a698e022 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -145,7 +145,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     fn visit_item(&mut self, i: &'hir Item<'hir>) {
         debug_assert_eq!(i.owner_id, self.owner);
         self.with_parent(i.hir_id(), |this| {
-            if let ItemKind::Struct(ref struct_def, _) = i.kind {
+            if let ItemKind::Struct(struct_def, _) = &i.kind {
                 // If this is a tuple or unit-like struct, register the constructor.
                 if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
                     this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def));
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 99b3ac864dd..a1941b5d8d3 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -142,7 +142,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
             // This is used to track which lifetimes have already been defined,
             // and which need to be replicated when lowering an async fn.
             match parent_hir.node().expect_item().kind {
-                hir::ItemKind::Impl(hir::Impl { ref of_trait, .. }) => {
+                hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
                     lctx.is_in_trait_impl = of_trait.is_some();
                 }
                 _ => {}
@@ -178,7 +178,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
         let mut node_ids =
             smallvec![hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }];
-        if let ItemKind::Use(ref use_tree) = &i.kind {
+        if let ItemKind::Use(use_tree) = &i.kind {
             self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids);
         }
         node_ids
@@ -190,8 +190,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         base_id: NodeId,
         vec: &mut SmallVec<[hir::ItemId; 1]>,
     ) {
-        match tree.kind {
-            UseTreeKind::Nested(ref nested_vec) => {
+        match &tree.kind {
+            UseTreeKind::Nested(nested_vec) => {
                 for &(ref nested, id) in nested_vec {
                     vec.push(hir::ItemId {
                         owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
@@ -201,8 +201,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
             UseTreeKind::Glob => {}
             UseTreeKind::Simple(_, id1, id2) => {
-                for (_, &id) in
-                    iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2])
+                for (_, id) in
+                    iter::zip(self.expect_full_res_from_use(base_id).skip(1), [*id1, *id2])
                 {
                     vec.push(hir::ItemId {
                         owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
@@ -238,26 +238,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
         vis_span: Span,
         i: &ItemKind,
     ) -> hir::ItemKind<'hir> {
-        match *i {
-            ItemKind::ExternCrate(orig_name) => hir::ItemKind::ExternCrate(orig_name),
-            ItemKind::Use(ref use_tree) => {
+        match i {
+            ItemKind::ExternCrate(orig_name) => hir::ItemKind::ExternCrate(*orig_name),
+            ItemKind::Use(use_tree) => {
                 // Start with an empty prefix.
                 let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None };
 
                 self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs)
             }
-            ItemKind::Static(ref t, m, ref e) => {
+            ItemKind::Static(t, m, e) => {
                 let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
-                hir::ItemKind::Static(ty, m, body_id)
+                hir::ItemKind::Static(ty, *m, body_id)
             }
-            ItemKind::Const(_, ref t, ref e) => {
+            ItemKind::Const(_, t, e) => {
                 let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
                 hir::ItemKind::Const(ty, body_id)
             }
             ItemKind::Fn(box Fn {
-                sig: FnSig { ref decl, header, span: fn_sig_span },
-                ref generics,
-                ref body,
+                sig: FnSig { decl, header, span: fn_sig_span },
+                generics,
+                body,
                 ..
             }) => {
                 self.with_new_scopes(|this| {
@@ -274,37 +274,30 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let mut itctx = ImplTraitContext::Universal;
                     let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
                         let ret_id = asyncness.opt_return_id();
-                        this.lower_fn_decl(&decl, Some(id), fn_sig_span, FnDeclKind::Fn, ret_id)
+                        this.lower_fn_decl(&decl, Some(id), *fn_sig_span, FnDeclKind::Fn, ret_id)
                     });
                     let sig = hir::FnSig {
                         decl,
-                        header: this.lower_fn_header(header),
-                        span: this.lower_span(fn_sig_span),
+                        header: this.lower_fn_header(*header),
+                        span: this.lower_span(*fn_sig_span),
                     };
                     hir::ItemKind::Fn(sig, generics, body_id)
                 })
             }
-            ItemKind::Mod(_, ref mod_kind) => match mod_kind {
+            ItemKind::Mod(_, mod_kind) => match mod_kind {
                 ModKind::Loaded(items, _, spans) => {
                     hir::ItemKind::Mod(self.lower_mod(items, spans))
                 }
                 ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
             },
-            ItemKind::ForeignMod(ref fm) => hir::ItemKind::ForeignMod {
+            ItemKind::ForeignMod(fm) => hir::ItemKind::ForeignMod {
                 abi: fm.abi.map_or(abi::Abi::FALLBACK, |abi| self.lower_abi(abi)),
                 items: self
                     .arena
                     .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
             },
-            ItemKind::GlobalAsm(ref asm) => {
-                hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm))
-            }
-            ItemKind::TyAlias(box TyAlias {
-                ref generics,
-                where_clauses,
-                ty: Some(ref ty),
-                ..
-            }) => {
+            ItemKind::GlobalAsm(asm) => hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm)),
+            ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty: Some(ty), .. }) => {
                 // We lower
                 //
                 // type Foo = impl Trait
@@ -314,7 +307,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 // type Foo = Foo1
                 // opaque type Foo1: Trait
                 let mut generics = generics.clone();
-                add_ty_alias_where_clause(&mut generics, where_clauses, true);
+                add_ty_alias_where_clause(&mut generics, *where_clauses, true);
                 let (generics, ty) = self.lower_generics(
                     &generics,
                     id,
@@ -323,9 +316,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::TyAlias(ty, generics)
             }
-            ItemKind::TyAlias(box TyAlias {
-                ref generics, ref where_clauses, ty: None, ..
-            }) => {
+            ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty: None, .. }) => {
                 let mut generics = generics.clone();
                 add_ty_alias_where_clause(&mut generics, *where_clauses, true);
                 let (generics, ty) = self.lower_generics(
@@ -336,7 +327,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::TyAlias(ty, generics)
             }
-            ItemKind::Enum(ref enum_definition, ref generics) => {
+            ItemKind::Enum(enum_definition, generics) => {
                 let (generics, variants) = self.lower_generics(
                     generics,
                     id,
@@ -349,7 +340,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::Enum(hir::EnumDef { variants }, generics)
             }
-            ItemKind::Struct(ref struct_def, ref generics) => {
+            ItemKind::Struct(struct_def, generics) => {
                 let (generics, struct_def) = self.lower_generics(
                     generics,
                     id,
@@ -358,7 +349,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::Struct(struct_def, generics)
             }
-            ItemKind::Union(ref vdata, ref generics) => {
+            ItemKind::Union(vdata, generics) => {
                 let (generics, vdata) = self.lower_generics(
                     generics,
                     id,
@@ -372,10 +363,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 polarity,
                 defaultness,
                 constness,
-                generics: ref ast_generics,
-                of_trait: ref trait_ref,
-                self_ty: ref ty,
-                items: ref impl_items,
+                generics: ast_generics,
+                of_trait: trait_ref,
+                self_ty: ty,
+                items: impl_items,
             }) => {
                 // Lower the "impl header" first. This ordering is important
                 // for in-band lifetimes! Consider `'a` here:
@@ -413,30 +404,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 // `defaultness.has_value()` is never called for an `impl`, always `true` in order
                 // to not cause an assertion failure inside the `lower_defaultness` function.
                 let has_val = true;
-                let (defaultness, defaultness_span) = self.lower_defaultness(defaultness, has_val);
+                let (defaultness, defaultness_span) = self.lower_defaultness(*defaultness, has_val);
                 let polarity = match polarity {
                     ImplPolarity::Positive => ImplPolarity::Positive,
-                    ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(s)),
+                    ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)),
                 };
                 hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
-                    unsafety: self.lower_unsafety(unsafety),
+                    unsafety: self.lower_unsafety(*unsafety),
                     polarity,
                     defaultness,
                     defaultness_span,
-                    constness: self.lower_constness(constness),
+                    constness: self.lower_constness(*constness),
                     generics,
                     of_trait: trait_ref,
                     self_ty: lowered_ty,
                     items: new_impl_items,
                 }))
             }
-            ItemKind::Trait(box Trait {
-                is_auto,
-                unsafety,
-                ref generics,
-                ref bounds,
-                ref items,
-            }) => {
+            ItemKind::Trait(box Trait { is_auto, unsafety, generics, bounds, items }) => {
                 let (generics, (unsafety, items, bounds)) = self.lower_generics(
                     generics,
                     id,
@@ -449,13 +434,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         let items = this.arena.alloc_from_iter(
                             items.iter().map(|item| this.lower_trait_item_ref(item)),
                         );
-                        let unsafety = this.lower_unsafety(unsafety);
+                        let unsafety = this.lower_unsafety(*unsafety);
                         (unsafety, items, bounds)
                     },
                 );
-                hir::ItemKind::Trait(is_auto, unsafety, generics, bounds, items)
+                hir::ItemKind::Trait(*is_auto, unsafety, generics, bounds, items)
             }
-            ItemKind::TraitAlias(ref generics, ref bounds) => {
+            ItemKind::TraitAlias(generics, bounds) => {
                 let (generics, bounds) = self.lower_generics(
                     generics,
                     id,
@@ -469,10 +454,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::TraitAlias(generics, bounds)
             }
-            ItemKind::MacroDef(MacroDef { ref body, macro_rules }) => {
+            ItemKind::MacroDef(MacroDef { body, macro_rules }) => {
                 let body = P(self.lower_delim_args(body));
                 let macro_kind = self.resolver.decl_macro_kind(self.local_def_id(id));
-                hir::ItemKind::Macro(ast::MacroDef { body, macro_rules }, macro_kind)
+                hir::ItemKind::Macro(ast::MacroDef { body, macro_rules: *macro_rules }, macro_kind)
             }
             ItemKind::MacCall(..) => {
                 panic!("`TyMac` should have been expanded by now")
@@ -664,8 +649,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let item = hir::ForeignItem {
             owner_id,
             ident: self.lower_ident(i.ident),
-            kind: match i.kind {
-                ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
+            kind: match &i.kind {
+                ForeignItemKind::Fn(box Fn { sig, generics, .. }) => {
                     let fdec = &sig.decl;
                     let mut itctx = ImplTraitContext::Universal;
                     let (generics, (fn_dec, fn_args)) =
@@ -685,10 +670,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
                     hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
                 }
-                ForeignItemKind::Static(ref t, m, _) => {
+                ForeignItemKind::Static(t, m, _) => {
                     let ty =
                         self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
-                    hir::ForeignItemKind::Static(ty, m)
+                    hir::ForeignItemKind::Static(ty, *m)
                 }
                 ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
                 ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
@@ -725,33 +710,33 @@ impl<'hir> LoweringContext<'_, 'hir> {
         parent_id: hir::HirId,
         vdata: &VariantData,
     ) -> hir::VariantData<'hir> {
-        match *vdata {
-            VariantData::Struct(ref fields, recovered) => hir::VariantData::Struct(
+        match vdata {
+            VariantData::Struct(fields, recovered) => hir::VariantData::Struct(
                 self.arena
                     .alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f))),
-                recovered,
+                *recovered,
             ),
-            VariantData::Tuple(ref fields, id) => {
-                let ctor_id = self.lower_node_id(id);
+            VariantData::Tuple(fields, id) => {
+                let ctor_id = self.lower_node_id(*id);
                 self.alias_attrs(ctor_id, parent_id);
                 hir::VariantData::Tuple(
                     self.arena.alloc_from_iter(
                         fields.iter().enumerate().map(|f| self.lower_field_def(f)),
                     ),
                     ctor_id,
-                    self.local_def_id(id),
+                    self.local_def_id(*id),
                 )
             }
             VariantData::Unit(id) => {
-                let ctor_id = self.lower_node_id(id);
+                let ctor_id = self.lower_node_id(*id);
                 self.alias_attrs(ctor_id, parent_id);
-                hir::VariantData::Unit(ctor_id, self.local_def_id(id))
+                hir::VariantData::Unit(ctor_id, self.local_def_id(*id))
             }
         }
     }
 
     fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'hir> {
-        let ty = if let TyKind::Path(ref qself, ref path) = f.ty.kind {
+        let ty = if let TyKind::Path(qself, path) = &f.ty.kind {
             let t = self.lower_path_ty(
                 &f.ty,
                 qself,
@@ -783,13 +768,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let hir_id = self.lower_node_id(i.id);
         let trait_item_def_id = hir_id.expect_owner();
 
-        let (generics, kind, has_default) = match i.kind {
-            AssocItemKind::Const(_, ref ty, ref default) => {
+        let (generics, kind, has_default) = match &i.kind {
+            AssocItemKind::Const(_, ty, default) => {
                 let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
                 let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
                 (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some())
             }
-            AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => {
+            AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => {
                 let asyncness = sig.header.asyncness;
                 let names = self.lower_fn_params_to_names(&sig.decl);
                 let (generics, sig) = self.lower_method_sig(
@@ -801,7 +786,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
             }
-            AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => {
+            AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
                 let asyncness = sig.header.asyncness;
                 let body_id =
                     self.lower_maybe_async_body(i.span, &sig.decl, asyncness, Some(&body));
@@ -814,15 +799,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
             }
-            AssocItemKind::Type(box TyAlias {
-                ref generics,
-                where_clauses,
-                ref bounds,
-                ref ty,
-                ..
-            }) => {
+            AssocItemKind::Type(box TyAlias { generics, where_clauses, bounds, ty, .. }) => {
                 let mut generics = generics.clone();
-                add_ty_alias_where_clause(&mut generics, where_clauses, false);
+                add_ty_alias_where_clause(&mut generics, *where_clauses, false);
                 let (generics, kind) = self.lower_generics(
                     &generics,
                     i.id,
@@ -1354,7 +1333,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // keep track of the Span info. Now, `add_implicitly_sized` in `AstConv` checks both param bounds and
         // where clauses for `?Sized`.
         for pred in &generics.where_clause.predicates {
-            let WherePredicate::BoundPredicate(ref bound_pred) = *pred else {
+            let WherePredicate::BoundPredicate(bound_pred) = pred else {
                 continue;
             };
             let compute_is_param = || {
@@ -1515,11 +1494,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> {
-        match *pred {
+        match pred {
             WherePredicate::BoundPredicate(WhereBoundPredicate {
-                ref bound_generic_params,
-                ref bounded_ty,
-                ref bounds,
+                bound_generic_params,
+                bounded_ty,
+                bounds,
                 span,
             }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
                 hir_id: self.next_id(),
@@ -1532,29 +1511,27 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         &ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
                     )
                 })),
-                span: self.lower_span(span),
+                span: self.lower_span(*span),
                 origin: PredicateOrigin::WhereClause,
             }),
-            WherePredicate::RegionPredicate(WhereRegionPredicate {
-                ref lifetime,
-                ref bounds,
-                span,
-            }) => hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
-                span: self.lower_span(span),
-                lifetime: self.lower_lifetime(lifetime),
-                bounds: self.lower_param_bounds(
-                    bounds,
-                    &ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
-                ),
-                in_where_clause: true,
-            }),
-            WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span }) => {
+            WherePredicate::RegionPredicate(WhereRegionPredicate { lifetime, bounds, span }) => {
+                hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
+                    span: self.lower_span(*span),
+                    lifetime: self.lower_lifetime(lifetime),
+                    bounds: self.lower_param_bounds(
+                        bounds,
+                        &ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
+                    ),
+                    in_where_clause: true,
+                })
+            }
+            WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span }) => {
                 hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
                     lhs_ty: self
                         .lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
                     rhs_ty: self
                         .lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
-                    span: self.lower_span(span),
+                    span: self.lower_span(*span),
                 })
             }
         }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index ce81a0ae959..d1666dfbf64 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -932,13 +932,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     fn lower_attr_args(&self, args: &AttrArgs) -> AttrArgs {
-        match *args {
+        match args {
             AttrArgs::Empty => AttrArgs::Empty,
-            AttrArgs::Delimited(ref args) => AttrArgs::Delimited(self.lower_delim_args(args)),
+            AttrArgs::Delimited(args) => AttrArgs::Delimited(self.lower_delim_args(args)),
             // This is an inert key-value attribute - it will never be visible to macros
             // after it gets lowered to HIR. Therefore, we can extract literals to handle
             // nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
-            AttrArgs::Eq(eq_span, AttrArgsEq::Ast(ref expr)) => {
+            AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => {
                 // In valid code the value always ends up as a single literal. Otherwise, a dummy
                 // literal suffices because the error is handled elsewhere.
                 let lit = if let ExprKind::Lit(token_lit) = expr.kind {
@@ -957,9 +957,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         span: DUMMY_SP,
                     }
                 };
-                AttrArgs::Eq(eq_span, AttrArgsEq::Hir(lit))
+                AttrArgs::Eq(*eq_span, AttrArgsEq::Hir(lit))
             }
-            AttrArgs::Eq(_, AttrArgsEq::Hir(ref lit)) => {
+            AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => {
                 unreachable!("in literal form when lowering mac args eq: {:?}", lit)
             }
         }
@@ -987,12 +987,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     ) -> hir::TypeBinding<'hir> {
         debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
         // lower generic arguments of identifier in constraint
-        let gen_args = if let Some(ref gen_args) = constraint.gen_args {
+        let gen_args = if let Some(gen_args) = &constraint.gen_args {
             let gen_args_ctor = match gen_args {
-                GenericArgs::AngleBracketed(ref data) => {
+                GenericArgs::AngleBracketed(data) => {
                     self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0
                 }
-                GenericArgs::Parenthesized(ref data) => {
+                GenericArgs::Parenthesized(data) => {
                     self.emit_bad_parenthesized_trait_in_assoc_ty(data);
                     let aba = self.ast_arena.aba.alloc(data.as_angle_bracketed_args());
                     self.lower_angle_bracketed_parameter_data(aba, ParamMode::Explicit, itctx).0
@@ -1004,15 +1004,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         };
         let itctx_tait = &ImplTraitContext::TypeAliasesOpaqueTy;
 
-        let kind = match constraint.kind {
-            AssocConstraintKind::Equality { ref term } => {
+        let kind = match &constraint.kind {
+            AssocConstraintKind::Equality { term } => {
                 let term = match term {
-                    Term::Ty(ref ty) => self.lower_ty(ty, itctx).into(),
-                    Term::Const(ref c) => self.lower_anon_const(c).into(),
+                    Term::Ty(ty) => self.lower_ty(ty, itctx).into(),
+                    Term::Const(c) => self.lower_anon_const(c).into(),
                 };
                 hir::TypeBindingKind::Equality { term }
             }
-            AssocConstraintKind::Bound { ref bounds } => {
+            AssocConstraintKind::Bound { bounds } => {
                 // Piggy-back on the `impl Trait` context to figure out the correct behavior.
                 let (desugar_to_impl_trait, itctx) = match itctx {
                     // We are in the return position:
@@ -1122,7 +1122,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         match arg {
             ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(&lt)),
             ast::GenericArg::Type(ty) => {
-                match ty.kind {
+                match &ty.kind {
                     TyKind::Infer if self.tcx.features().generic_arg_infer => {
                         return GenericArg::Infer(hir::InferArg {
                             hir_id: self.lower_node_id(ty.id),
@@ -1133,7 +1133,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     // parsing. We try to resolve that ambiguity by attempting resolution in both the
                     // type and value namespaces. If we resolved the path in the value namespace, we
                     // transform it into a generic const argument.
-                    TyKind::Path(ref qself, ref path) => {
+                    TyKind::Path(qself, path) => {
                         if let Some(res) = self
                             .resolver
                             .get_partial_res(ty.id)
@@ -1240,12 +1240,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> {
-        let kind = match t.kind {
+        let kind = match &t.kind {
             TyKind::Infer => hir::TyKind::Infer,
             TyKind::Err => hir::TyKind::Err,
-            TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
-            TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
-            TyKind::Rptr(ref region, ref mt) => {
+            TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
+            TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
+            TyKind::Rptr(region, mt) => {
                 let region = region.unwrap_or_else(|| {
                     let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
                         self.resolver.get_lifetime_res(t.id)
@@ -1261,7 +1261,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 let lifetime = self.lower_lifetime(&region);
                 hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
             }
-            TyKind::BareFn(ref f) => {
+            TyKind::BareFn(f) => {
                 let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
                 hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy {
                     generic_params,
@@ -1272,13 +1272,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 }))
             }
             TyKind::Never => hir::TyKind::Never,
-            TyKind::Tup(ref tys) => hir::TyKind::Tup(
+            TyKind::Tup(tys) => hir::TyKind::Tup(
                 self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))),
             ),
-            TyKind::Paren(ref ty) => {
+            TyKind::Paren(ty) => {
                 return self.lower_ty_direct(ty, itctx);
             }
-            TyKind::Path(ref qself, ref path) => {
+            TyKind::Path(qself, path) => {
                 return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx);
             }
             TyKind::ImplicitSelf => {
@@ -1298,48 +1298,46 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     }),
                 ))
             }
-            TyKind::Array(ref ty, ref length) => {
+            TyKind::Array(ty, length) => {
                 hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length))
             }
-            TyKind::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)),
-            TyKind::TraitObject(ref bounds, kind) => {
+            TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)),
+            TyKind::TraitObject(bounds, kind) => {
                 let mut lifetime_bound = None;
                 let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
                     let bounds =
-                        this.arena.alloc_from_iter(bounds.iter().filter_map(
-                            |bound| match *bound {
-                                GenericBound::Trait(
-                                    ref ty,
-                                    TraitBoundModifier::None | TraitBoundModifier::MaybeConst,
-                                ) => Some(this.lower_poly_trait_ref(ty, itctx)),
-                                // `~const ?Bound` will cause an error during AST validation
-                                // anyways, so treat it like `?Bound` as compilation proceeds.
-                                GenericBound::Trait(
-                                    _,
-                                    TraitBoundModifier::Maybe | TraitBoundModifier::MaybeConstMaybe,
-                                ) => None,
-                                GenericBound::Outlives(ref lifetime) => {
-                                    if lifetime_bound.is_none() {
-                                        lifetime_bound = Some(this.lower_lifetime(lifetime));
-                                    }
-                                    None
+                        this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {
+                            GenericBound::Trait(
+                                ty,
+                                TraitBoundModifier::None | TraitBoundModifier::MaybeConst,
+                            ) => Some(this.lower_poly_trait_ref(ty, itctx)),
+                            // `~const ?Bound` will cause an error during AST validation
+                            // anyways, so treat it like `?Bound` as compilation proceeds.
+                            GenericBound::Trait(
+                                _,
+                                TraitBoundModifier::Maybe | TraitBoundModifier::MaybeConstMaybe,
+                            ) => None,
+                            GenericBound::Outlives(lifetime) => {
+                                if lifetime_bound.is_none() {
+                                    lifetime_bound = Some(this.lower_lifetime(lifetime));
                                 }
-                            },
-                        ));
+                                None
+                            }
+                        }));
                     let lifetime_bound =
                         lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span));
                     (bounds, lifetime_bound)
                 });
-                hir::TyKind::TraitObject(bounds, lifetime_bound, kind)
+                hir::TyKind::TraitObject(bounds, lifetime_bound, *kind)
             }
-            TyKind::ImplTrait(def_node_id, ref bounds) => {
+            TyKind::ImplTrait(def_node_id, bounds) => {
                 let span = t.span;
                 match itctx {
                     ImplTraitContext::ReturnPositionOpaqueTy { origin, in_trait } => self
                         .lower_opaque_impl_trait(
                             span,
                             *origin,
-                            def_node_id,
+                            *def_node_id,
                             bounds,
                             *in_trait,
                             itctx,
@@ -1347,7 +1345,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait(
                         span,
                         hir::OpaqueTyOrigin::TyAlias,
-                        def_node_id,
+                        *def_node_id,
                         bounds,
                         false,
                         itctx,
@@ -1355,13 +1353,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     ImplTraitContext::Universal => {
                         self.create_def(
                             self.current_hir_id_owner.def_id,
-                            def_node_id,
+                            *def_node_id,
                             DefPathData::ImplTrait,
                         );
                         let span = t.span;
                         let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
                         let (param, bounds, path) =
-                            self.lower_generic_and_bounds(def_node_id, span, ident, bounds);
+                            self.lower_generic_and_bounds(*def_node_id, span, ident, bounds);
                         self.impl_trait_defs.push(param);
                         if let Some(bounds) = bounds {
                             self.impl_trait_bounds.push(bounds);
@@ -1740,8 +1738,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 matches!(kind, FnDeclKind::Trait),
             )
         } else {
-            match decl.output {
-                FnRetTy::Ty(ref ty) => {
+            match &decl.output {
+                FnRetTy::Ty(ty) => {
                     let mut context = match fn_node_id {
                         Some(fn_node_id) if kind.impl_trait_allowed(self.tcx) => {
                             let fn_def_id = self.local_def_id(fn_node_id);
@@ -1763,7 +1761,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     };
                     hir::FnRetTy::Return(self.lower_ty(ty, &mut context))
                 }
-                FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(span)),
+                FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)),
             }
         };
 
@@ -1777,18 +1775,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     PatKind::Ident(hir::BindingAnnotation(_, Mutability::Mut), ..)
                 );
 
-                match arg.ty.kind {
+                match &arg.ty.kind {
                     TyKind::ImplicitSelf if is_mutable_pat => hir::ImplicitSelfKind::Mut,
                     TyKind::ImplicitSelf => hir::ImplicitSelfKind::Imm,
                     // Given we are only considering `ImplicitSelf` types, we needn't consider
                     // the case where we have a mutable pattern to a reference as that would
                     // no longer be an `ImplicitSelf`.
-                    TyKind::Rptr(_, ref mt)
+                    TyKind::Rptr(_, mt)
                         if mt.ty.kind.is_implicit_self() && mt.mutbl == ast::Mutability::Mut =>
                     {
                         hir::ImplicitSelfKind::MutRef
                     }
-                    TyKind::Rptr(_, ref mt) if mt.ty.kind.is_implicit_self() => {
+                    TyKind::Rptr(_, mt) if mt.ty.kind.is_implicit_self() => {
                         hir::ImplicitSelfKind::ImmRef
                     }
                     _ => hir::ImplicitSelfKind::None,
@@ -1817,9 +1815,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
 
-        let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id);
         let fn_def_id = self.local_def_id(fn_node_id);
 
+        let opaque_ty_def_id =
+            self.create_def(fn_def_id, opaque_ty_node_id, DefPathData::ImplTrait);
+
         // When we create the opaque type for this async fn, it is going to have
         // to capture all the lifetimes involved in the signature (including in the
         // return type). This is done by introducing lifetime parameters for:
@@ -2179,7 +2179,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         &mut self,
         param: &GenericParam,
     ) -> (hir::ParamName, hir::GenericParamKind<'hir>) {
-        match param.kind {
+        match &param.kind {
             GenericParamKind::Lifetime => {
                 // AST resolution emitted an error on those parameters, so we lower them using
                 // `ParamName::Error`.
@@ -2195,7 +2195,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
                 (param_name, kind)
             }
-            GenericParamKind::Type { ref default, .. } => {
+            GenericParamKind::Type { default, .. } => {
                 let kind = hir::GenericParamKind::Type {
                     default: default.as_ref().map(|x| {
                         self.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type))
@@ -2205,7 +2205,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
                 (hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
             }
-            GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
+            GenericParamKind::Const { ty, kw_span: _, default } => {
                 let ty = self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
                 let default = default.as_ref().map(|def| self.lower_anon_const(def));
                 (
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index 7fdfc79164b..16b012630da 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -22,16 +22,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         ensure_sufficient_stack(|| {
             // loop here to avoid recursion
             let node = loop {
-                match pattern.kind {
+                match &pattern.kind {
                     PatKind::Wild => break hir::PatKind::Wild,
-                    PatKind::Ident(binding_mode, ident, ref sub) => {
-                        let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s));
-                        break self.lower_pat_ident(pattern, binding_mode, ident, lower_sub);
+                    PatKind::Ident(binding_mode, ident, sub) => {
+                        let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(s));
+                        break self.lower_pat_ident(pattern, *binding_mode, *ident, lower_sub);
                     }
-                    PatKind::Lit(ref e) => {
+                    PatKind::Lit(e) => {
                         break hir::PatKind::Lit(self.lower_expr_within_pat(e, false));
                     }
-                    PatKind::TupleStruct(ref qself, ref path, ref pats) => {
+                    PatKind::TupleStruct(qself, path, pats) => {
                         let qpath = self.lower_qpath(
                             pattern.id,
                             qself,
@@ -42,12 +42,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
                         break hir::PatKind::TupleStruct(qpath, pats, ddpos);
                     }
-                    PatKind::Or(ref pats) => {
+                    PatKind::Or(pats) => {
                         break hir::PatKind::Or(
                             self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat_mut(x))),
                         );
                     }
-                    PatKind::Path(ref qself, ref path) => {
+                    PatKind::Path(qself, path) => {
                         let qpath = self.lower_qpath(
                             pattern.id,
                             qself,
@@ -57,7 +57,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         );
                         break hir::PatKind::Path(qpath);
                     }
-                    PatKind::Struct(ref qself, ref path, ref fields, etc) => {
+                    PatKind::Struct(qself, path, fields, etc) => {
                         let qpath = self.lower_qpath(
                             pattern.id,
                             qself,
@@ -78,32 +78,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                 span: self.lower_span(f.span),
                             }
                         }));
-                        break hir::PatKind::Struct(qpath, fs, etc);
+                        break hir::PatKind::Struct(qpath, fs, *etc);
                     }
-                    PatKind::Tuple(ref pats) => {
+                    PatKind::Tuple(pats) => {
                         let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");
                         break hir::PatKind::Tuple(pats, ddpos);
                     }
-                    PatKind::Box(ref inner) => {
+                    PatKind::Box(inner) => {
                         break hir::PatKind::Box(self.lower_pat(inner));
                     }
-                    PatKind::Ref(ref inner, mutbl) => {
-                        break hir::PatKind::Ref(self.lower_pat(inner), mutbl);
+                    PatKind::Ref(inner, mutbl) => {
+                        break hir::PatKind::Ref(self.lower_pat(inner), *mutbl);
                     }
-                    PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => {
+                    PatKind::Range(e1, e2, Spanned { node: end, .. }) => {
                         break hir::PatKind::Range(
                             e1.as_deref().map(|e| self.lower_expr_within_pat(e, true)),
                             e2.as_deref().map(|e| self.lower_expr_within_pat(e, true)),
                             self.lower_range_end(end, e2.is_some()),
                         );
                     }
-                    PatKind::Slice(ref pats) => break self.lower_pat_slice(pats),
+                    PatKind::Slice(pats) => break self.lower_pat_slice(pats),
                     PatKind::Rest => {
                         // If we reach here the `..` pattern is not semantically allowed.
                         break self.ban_illegal_rest_pat(pattern.span);
                     }
                     // return inner to be processed in next loop
-                    PatKind::Paren(ref inner) => pattern = inner,
+                    PatKind::Paren(inner) => pattern = inner,
                     PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span),
                 }
             };
@@ -126,7 +126,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // Note that unlike for slice patterns,
             // where `xs @ ..` is a legal sub-slice pattern,
             // it is not a legal sub-tuple pattern.
-            match pat.kind {
+            match &pat.kind {
                 // Found a sub-tuple rest pattern
                 PatKind::Rest => {
                     rest = Some((idx, pat.span));
@@ -134,12 +134,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 }
                 // Found a sub-tuple pattern `$binding_mode $ident @ ..`.
                 // This is not allowed as a sub-tuple pattern
-                PatKind::Ident(ref _bm, ident, Some(ref sub)) if sub.is_rest() => {
+                PatKind::Ident(_, ident, Some(sub)) if sub.is_rest() => {
                     let sp = pat.span;
                     self.tcx.sess.emit_err(SubTupleBinding {
                         span: sp,
                         ident_name: ident.name,
-                        ident,
+                        ident: *ident,
                         ctx,
                     });
                 }
@@ -176,7 +176,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let mut prev_rest_span = None;
 
         // Lowers `$bm $ident @ ..` to `$bm $ident @ _`.
-        let lower_rest_sub = |this: &mut Self, pat, ann, ident, sub| {
+        let lower_rest_sub = |this: &mut Self, pat, &ann, &ident, sub| {
             let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
             let node = this.lower_pat_ident(pat, ann, ident, lower_sub);
             this.pat_with_node_id_of(pat, node)
@@ -185,7 +185,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let mut iter = pats.iter();
         // Lower all the patterns until the first occurrence of a sub-slice pattern.
         for pat in iter.by_ref() {
-            match pat.kind {
+            match &pat.kind {
                 // Found a sub-slice pattern `..`. Record, lower it to `_`, and stop here.
                 PatKind::Rest => {
                     prev_rest_span = Some(pat.span);
@@ -194,7 +194,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 }
                 // Found a sub-slice pattern `$binding_mode $ident @ ..`.
                 // Record, lower it to `$binding_mode $ident @ _`, and stop here.
-                PatKind::Ident(ann, ident, Some(ref sub)) if sub.is_rest() => {
+                PatKind::Ident(ann, ident, Some(sub)) if sub.is_rest() => {
                     prev_rest_span = Some(sub.span);
                     slice = Some(self.arena.alloc(lower_rest_sub(self, pat, ann, ident, sub)));
                     break;
@@ -207,9 +207,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // Lower all the patterns after the first sub-slice pattern.
         for pat in iter {
             // There was a previous subslice pattern; make sure we don't allow more.
-            let rest_span = match pat.kind {
+            let rest_span = match &pat.kind {
                 PatKind::Rest => Some(pat.span),
-                PatKind::Ident(ann, ident, Some(ref sub)) if sub.is_rest() => {
+                PatKind::Ident(ann, ident, Some(sub)) if sub.is_rest() => {
                     // #69103: Lower into `binding @ _` as above to avoid ICEs.
                     after.push(lower_rest_sub(self, pat, ann, ident, sub));
                     Some(sub.span)
@@ -322,13 +322,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     // m!(S);
     // ```
     fn lower_expr_within_pat(&mut self, expr: &Expr, allow_paths: bool) -> &'hir hir::Expr<'hir> {
-        match expr.kind {
+        match &expr.kind {
             ExprKind::Lit(..)
             | ExprKind::ConstBlock(..)
             | ExprKind::IncludedBytes(..)
             | ExprKind::Err => {}
             ExprKind::Path(..) if allow_paths => {}
-            ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
+            ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
             _ => {
                 self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span });
                 return self.arena.alloc(self.expr_err(expr.span));
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 83d459d899b..27b44c0b6a2 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -185,12 +185,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         itctx: &ImplTraitContext,
     ) -> hir::PathSegment<'hir> {
         debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,);
-        let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args {
-            match **generic_args {
-                GenericArgs::AngleBracketed(ref data) => {
+        let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() {
+            match generic_args {
+                GenericArgs::AngleBracketed(data) => {
                     self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
                 }
-                GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
+                GenericArgs::Parenthesized(data) => match parenthesized_generic_args {
                     ParenthesizedGenericArgs::Ok => {
                         self.lower_parenthesized_parameter_data(data, itctx)
                     }
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 712fb5ac71f..acd7eb69ffc 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1637,7 +1637,7 @@ fn deny_equality_constraints(
                                     // Remove `Bar` from `Foo::Bar`.
                                     assoc_path.segments.pop();
                                     let len = assoc_path.segments.len() - 1;
-                                    let gen_args = args.as_ref().map(|p| (**p).clone());
+                                    let gen_args = args.as_deref().cloned();
                                     // Build `<Bar = RhsTy>`.
                                     let arg = AngleBracketedArg::Constraint(AssocConstraint {
                                         id: rustc_ast::node_id::DUMMY_NODE_ID,
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 1da40d2302e..4b37fa027f5 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -377,7 +377,7 @@ impl<'a> State<'a> {
                 self.space();
                 self.print_block_with_attrs(blk, attrs);
             }
-            ast::ExprKind::Loop(ref blk, opt_label) => {
+            ast::ExprKind::Loop(ref blk, opt_label, _) => {
                 if let Some(label) = opt_label {
                     self.print_ident(label.ident);
                     self.word_space(":");
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 8f1ae594a92..5c645c66cd7 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -7,7 +7,7 @@ use rustc_errors::{
 };
 use rustc_hir as hir;
 use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
-use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
+use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::mir::tcx::PlaceTy;
@@ -167,10 +167,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 );
             }
 
-            self.add_moved_or_invoked_closure_note(location, used_place, &mut err);
+            let closure = self.add_moved_or_invoked_closure_note(location, used_place, &mut err);
 
             let mut is_loop_move = false;
             let mut in_pattern = false;
+            let mut seen_spans = FxHashSet::default();
 
             for move_site in &move_site_vec {
                 let move_out = self.move_data.moves[(*move_site).moi];
@@ -191,37 +192,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     is_loop_move = true;
                 }
 
-                self.explain_captures(
-                    &mut err,
-                    span,
-                    move_span,
-                    move_spans,
-                    *moved_place,
-                    partially_str,
-                    loop_message,
-                    move_msg,
-                    is_loop_move,
-                    maybe_reinitialized_locations.is_empty(),
-                );
-
-                if let (UseSpans::PatUse(span), []) =
-                    (move_spans, &maybe_reinitialized_locations[..])
-                {
-                    if maybe_reinitialized_locations.is_empty() {
-                        err.span_suggestion_verbose(
-                            span.shrink_to_lo(),
-                            &format!(
-                                "borrow this field in the pattern to avoid moving {}",
-                                self.describe_place(moved_place.as_ref())
-                                    .map(|n| format!("`{}`", n))
-                                    .unwrap_or_else(|| "the value".to_string())
-                            ),
-                            "ref ",
-                            Applicability::MachineApplicable,
-                        );
-                        in_pattern = true;
+                if !seen_spans.contains(&move_span) {
+                    if !closure {
+                        self.suggest_ref_or_clone(mpi, move_span, &mut err, &mut in_pattern);
                     }
+
+                    self.explain_captures(
+                        &mut err,
+                        span,
+                        move_span,
+                        move_spans,
+                        *moved_place,
+                        partially_str,
+                        loop_message,
+                        move_msg,
+                        is_loop_move,
+                        maybe_reinitialized_locations.is_empty(),
+                    );
                 }
+                seen_spans.insert(move_span);
             }
 
             use_spans.var_path_only_subdiag(&mut err, desired_action);
@@ -317,6 +306,160 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
     }
 
+    fn suggest_ref_or_clone(
+        &mut self,
+        mpi: MovePathIndex,
+        move_span: Span,
+        err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
+        in_pattern: &mut bool,
+    ) {
+        struct ExpressionFinder<'hir> {
+            expr_span: Span,
+            expr: Option<&'hir hir::Expr<'hir>>,
+            pat: Option<&'hir hir::Pat<'hir>>,
+            parent_pat: Option<&'hir hir::Pat<'hir>>,
+        }
+        impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
+            fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
+                if e.span == self.expr_span {
+                    self.expr = Some(e);
+                }
+                hir::intravisit::walk_expr(self, e);
+            }
+            fn visit_pat(&mut self, p: &'hir hir::Pat<'hir>) {
+                if p.span == self.expr_span {
+                    self.pat = Some(p);
+                }
+                if let hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, i, sub) = p.kind {
+                    if i.span == self.expr_span || p.span == self.expr_span {
+                        self.pat = Some(p);
+                    }
+                    // Check if we are in a situation of `ident @ ident` where we want to suggest
+                    // `ref ident @ ref ident` or `ref ident @ Struct { ref ident }`.
+                    if let Some(subpat) = sub && self.pat.is_none() {
+                        self.visit_pat(subpat);
+                        if self.pat.is_some() {
+                            self.parent_pat = Some(p);
+                        }
+                        return;
+                    }
+                }
+                hir::intravisit::walk_pat(self, p);
+            }
+        }
+        let hir = self.infcx.tcx.hir();
+        if let Some(hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::Fn(_, _, body_id),
+            ..
+        })) = hir.find(hir.local_def_id_to_hir_id(self.mir_def_id()))
+            && let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id)
+        {
+            let place = &self.move_data.move_paths[mpi].place;
+            let span = place.as_local()
+                .map(|local| self.body.local_decls[local].source_info.span);
+            let mut finder = ExpressionFinder {
+                expr_span: move_span,
+                expr: None,
+                pat: None,
+                parent_pat: None,
+            };
+            finder.visit_expr(expr);
+            if let Some(span) = span && let Some(expr) = finder.expr {
+                for (_, expr) in hir.parent_iter(expr.hir_id) {
+                    if let hir::Node::Expr(expr) = expr {
+                        if expr.span.contains(span) {
+                            // If the let binding occurs within the same loop, then that
+                            // loop isn't relevant, like in the following, the outermost `loop`
+                            // doesn't play into `x` being moved.
+                            // ```
+                            // loop {
+                            //     let x = String::new();
+                            //     loop {
+                            //         foo(x);
+                            //     }
+                            // }
+                            // ```
+                            break;
+                        }
+                        if let hir::ExprKind::Loop(.., loop_span) = expr.kind {
+                            err.span_label(loop_span, "inside of this loop");
+                        }
+                    }
+                }
+                let typeck = self.infcx.tcx.typeck(self.mir_def_id());
+                let hir_id = hir.get_parent_node(expr.hir_id);
+                if let Some(parent) = hir.find(hir_id) {
+                    let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
+                        && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
+                        && let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id)
+                    {
+                        (def_id.as_local(), args, 1)
+                    } else if let hir::Node::Expr(parent_expr) = parent
+                        && let hir::ExprKind::Call(call, args) = parent_expr.kind
+                        && let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind()
+                    {
+                        (def_id.as_local(), args, 0)
+                    } else {
+                        (None, &[][..], 0)
+                    };
+                    if let Some(def_id) = def_id
+                        && let Some(node) = hir.find(hir.local_def_id_to_hir_id(def_id))
+                        && let Some(fn_sig) = node.fn_sig()
+                        && let Some(ident) = node.ident()
+                        && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
+                        && let Some(arg) = fn_sig.decl.inputs.get(pos + offset)
+                    {
+                        let mut span: MultiSpan = arg.span.into();
+                        span.push_span_label(
+                            arg.span,
+                            "this parameter takes ownership of the value".to_string(),
+                        );
+                        let descr = match node.fn_kind() {
+                            Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function",
+                            Some(hir::intravisit::FnKind::Method(..)) => "method",
+                            Some(hir::intravisit::FnKind::Closure) => "closure",
+                        };
+                        span.push_span_label(
+                            ident.span,
+                            format!("in this {descr}"),
+                        );
+                        err.span_note(
+                            span,
+                            format!(
+                                "consider changing this parameter type in {descr} `{ident}` to \
+                                 borrow instead if owning the value isn't necessary",
+                            ),
+                        );
+                    }
+                    let place = &self.move_data.move_paths[mpi].place;
+                    let ty = place.ty(self.body, self.infcx.tcx).ty;
+                    if let hir::Node::Expr(parent_expr) = parent
+                        && let hir::ExprKind::Call(call_expr, _) = parent_expr.kind
+                        && let hir::ExprKind::Path(
+                            hir::QPath::LangItem(LangItem::IntoIterIntoIter, _, _)
+                        ) = call_expr.kind
+                    {
+                        // Do not suggest `.clone()` in a `for` loop, we already suggest borrowing.
+                    } else {
+                        self.suggest_cloning(err, ty, move_span);
+                    }
+                }
+            }
+            if let Some(pat) = finder.pat {
+                *in_pattern = true;
+                let mut sugg = vec![(pat.span.shrink_to_lo(), "ref ".to_string())];
+                if let Some(pat) = finder.parent_pat {
+                    sugg.insert(0, (pat.span.shrink_to_lo(), "ref ".to_string()));
+                }
+                err.multipart_suggestion_verbose(
+                    "borrow this binding in the pattern to avoid moving the value",
+                    sugg,
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+    }
+
     fn report_use_of_uninitialized(
         &self,
         mpi: MovePathIndex,
@@ -590,6 +733,27 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         true
     }
 
+    fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
+        let tcx = self.infcx.tcx;
+        // Try to find predicates on *generic params* that would allow copying `ty`
+        let infcx = tcx.infer_ctxt().build();
+        if infcx
+            .type_implements_trait(
+                tcx.lang_items().clone_trait().unwrap(),
+                [tcx.erase_regions(ty)],
+                self.param_env,
+            )
+            .must_apply_modulo_regions()
+        {
+            err.span_suggestion_verbose(
+                span.shrink_to_hi(),
+                "consider cloning the value if the performance cost is acceptable",
+                ".clone()".to_string(),
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+
     fn suggest_adding_copy_bounds(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
         let tcx = self.infcx.tcx;
         let generics = tcx.generics_of(self.mir_def_id());
@@ -601,7 +765,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         else { return; };
         // Try to find predicates on *generic params* that would allow copying `ty`
         let infcx = tcx.infer_ctxt().build();
-        let copy_did = infcx.tcx.lang_items().copy_trait().unwrap();
+        let copy_did = infcx.tcx.require_lang_item(LangItem::Copy, Some(span));
         let cause = ObligationCause::new(
             span,
             self.mir_hir_id(),
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 7f26af67c71..c500cbc49e4 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -70,7 +70,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         location: Location,
         place: PlaceRef<'tcx>,
         diag: &mut Diagnostic,
-    ) {
+    ) -> bool {
         debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);
         let mut target = place.local_or_deref_local();
         for stmt in &self.body[location.block].statements[location.statement_index..] {
@@ -106,7 +106,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         {
                             place.local_or_deref_local().unwrap()
                         }
-                        _ => return,
+                        _ => return false,
                     };
 
                     debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
@@ -125,7 +125,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                     ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
                                 ),
                             );
-                            return;
+                            return true;
                         }
                     }
                 }
@@ -149,9 +149,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
                         ),
                     );
+                    return true;
                 }
             }
         }
+        false
     }
 
     /// End-user visible description of `place` if one can be found.
@@ -350,7 +352,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     } else {
                         def.non_enum_variant()
                     };
-                    if !including_tuple_field.0 && variant.ctor_kind == CtorKind::Fn {
+                    if !including_tuple_field.0 && variant.ctor_kind() == Some(CtorKind::Fn) {
                         return None;
                     }
                     Some(variant.fields[field.index()].name.to_string())
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 76f249dac51..534675f1dc0 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -21,7 +21,7 @@ use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::Region;
 use rustc_middle::ty::TypeVisitor;
 use rustc_middle::ty::{self, RegionVid, Ty};
-use rustc_span::symbol::{kw, sym, Ident};
+use rustc_span::symbol::{kw, Ident};
 use rustc_span::Span;
 
 use crate::borrowck_errors;
@@ -514,8 +514,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             span: *span,
             ty_err: match output_ty.kind() {
                 ty::Closure(_, _) => FnMutReturnTypeErr::ReturnClosure { span: *span },
-                ty::Adt(def, _)
-                    if self.infcx.tcx.is_diagnostic_item(sym::gen_future, def.did()) =>
+                ty::Generator(def, ..)
+                    if matches!(
+                        self.infcx.tcx.generator_kind(def),
+                        Some(hir::GeneratorKind::Async(_))
+                    ) =>
                 {
                     FnMutReturnTypeErr::ReturnAsyncBlock { span: *span }
                 }
@@ -927,10 +930,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     // only when the block is a closure
                     if let hir::ExprKind::Closure(hir::Closure {
                         capture_clause: hir::CaptureBy::Ref,
+                        body,
                         ..
                     }) = expr.kind
                     {
-                        closure_span = Some(expr.span.shrink_to_lo());
+                        let body = map.body(*body);
+                        if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) {
+                            closure_span = Some(expr.span.shrink_to_lo());
+                        }
                     }
                 }
             }
diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs
index 8a87d1972eb..89ac0dfa4d6 100644
--- a/compiler/rustc_borrowck/src/places_conflict.rs
+++ b/compiler/rustc_borrowck/src/places_conflict.rs
@@ -320,16 +320,10 @@ fn place_projection_conflict<'tcx>(
             debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF");
             Overlap::EqualOrDisjoint
         }
-        (ProjectionElem::OpaqueCast(v1), ProjectionElem::OpaqueCast(v2)) => {
-            if v1 == v2 {
-                // same type - recur.
-                debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE");
-                Overlap::EqualOrDisjoint
-            } else {
-                // Different types. Disjoint!
-                debug!("place_element_conflict: DISJOINT-OPAQUE");
-                Overlap::Disjoint
-            }
+        (ProjectionElem::OpaqueCast(_), ProjectionElem::OpaqueCast(_)) => {
+            // casts to other types may always conflict irrespective of the type being cast to.
+            debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE");
+            Overlap::EqualOrDisjoint
         }
         (ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => {
             if f1 == f2 {
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 7467212bed8..b268eac97d0 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -2588,7 +2588,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
 
             // For closures, we have some **extra requirements** we
-            //
             // have to check. In particular, in their upvars and
             // signatures, closures often reference various regions
             // from the surrounding function -- we call those the
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 94d51032866..b2702eafd33 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -2,9 +2,8 @@ use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRe
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_infer::traits::PredicateObligations;
 use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::relate::TypeRelation;
-use rustc_middle::ty::{self, Const, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
 use rustc_trait_selection::traits::query::Fallible;
 
@@ -141,13 +140,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
         );
     }
 
-    // We don't have to worry about the equality of consts during borrow checking
-    // as consts always have a static lifetime.
-    // FIXME(oli-obk): is this really true? We can at least have HKL and with
-    // inline consts we may have further lifetimes that may be unsound to treat as
-    // 'static.
-    fn const_equate(&mut self, _a: Const<'tcx>, _b: Const<'tcx>) {}
-
     fn normalization() -> NormalizationStrategy {
         NormalizationStrategy::Eager
     }
@@ -156,10 +148,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
         true
     }
 
-    fn register_opaque_type_obligations(
-        &mut self,
-        obligations: PredicateObligations<'tcx>,
-    ) -> Result<(), TypeError<'tcx>> {
+    fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
         self.type_checker
             .fully_perform_op(
                 self.locations,
@@ -172,6 +161,5 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
                 },
             )
             .unwrap();
-        Ok(())
     }
 }
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index a34c17a4258..900c4427424 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -564,7 +564,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
         let template_snippet = ecx.source_map().span_to_snippet(template_sp).ok();
         template_strs.push((
             template_str,
-            template_snippet.as_ref().map(|s| Symbol::intern(s)),
+            template_snippet.as_deref().map(Symbol::intern),
             template_sp,
         ));
         let template_str = template_str.as_str();
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index 220b7a8ad0f..9f42a0c2d58 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -307,7 +307,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
             | ExprKind::InlineAsm(_)
             | ExprKind::Let(_, _, _)
             | ExprKind::Lit(_)
-            | ExprKind::Loop(_, _)
+            | ExprKind::Loop(_, _, _)
             | ExprKind::MacCall(_)
             | ExprKind::Match(_, _)
             | ExprKind::Path(_, _)
diff --git a/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs b/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs
index fc7442470ac..df773910dbc 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs
@@ -100,7 +100,7 @@ fn test_iter() {
     let s = "The %d'th word %% is: `%.*s` %!\n";
     let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate().ok()).collect();
     assert_eq!(
-        subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(),
+        subs.iter().map(Option::as_deref).collect::<Vec<_>>(),
         vec![Some("{}"), None, Some("{:.*}"), None]
     );
 }
diff --git a/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs b/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs
index f5f82732f20..93a7afcd6e8 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs
@@ -39,7 +39,7 @@ fn test_iter() {
     let s = "The $0'th word $$ is: `$WORD` $!\n";
     let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate().ok()).collect();
     assert_eq!(
-        subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(),
+        subs.iter().map(Option::as_deref).collect::<Vec<_>>(),
         vec![Some("{0}"), None, Some("{WORD}")]
     );
 }
diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs
index 48da64906e2..c627af4e62f 100644
--- a/compiler/rustc_codegen_cranelift/build_system/utils.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs
@@ -104,5 +104,5 @@ pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) {
 }
 
 pub(crate) fn is_ci() -> bool {
-    env::var("CI").as_ref().map(|val| &**val) == Ok("true")
+    env::var("CI").as_deref() == Ok("true")
 }
diff --git a/compiler/rustc_codegen_cranelift/src/config.rs b/compiler/rustc_codegen_cranelift/src/config.rs
index e59a0cb0a23..45522fb1a4c 100644
--- a/compiler/rustc_codegen_cranelift/src/config.rs
+++ b/compiler/rustc_codegen_cranelift/src/config.rs
@@ -2,7 +2,7 @@ use std::env;
 use std::str::FromStr;
 
 fn bool_env_var(key: &str) -> bool {
-    env::var(key).as_ref().map(|val| &**val) == Ok("1")
+    env::var(key).as_deref() == Ok("1")
 }
 
 /// The mode to use for compilation.
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 8a8d889a298..86580d05d41 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -174,7 +174,7 @@ impl CoverageMapGenerator {
         counter_regions.sort_unstable_by_key(|(_counter, region)| *region);
         for (counter, region) in counter_regions {
             let CodeRegion { file_name, start_line, start_col, end_line, end_col } = *region;
-            let same_file = current_file_name.as_ref().map_or(false, |p| *p == file_name);
+            let same_file = current_file_name.map_or(false, |p| p == file_name);
             if !same_file {
                 if current_file_name.is_some() {
                     current_file_id += 1;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 163ccd9460c..d87117dffdc 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -998,7 +998,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
                 .iter()
                 .enumerate()
                 .map(|(i, f)| {
-                    let field_name = if variant_def.ctor_kind == CtorKind::Fn {
+                    let field_name = if variant_def.ctor_kind() == Some(CtorKind::Fn) {
                         // This is a tuple struct
                         tuple_field_name(i)
                     } else {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index cb558a50d91..564ab351bd4 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -269,7 +269,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
         |cx, struct_type_di_node| {
             (0..variant_layout.fields.count())
                 .map(|field_index| {
-                    let field_name = if variant_def.ctor_kind != CtorKind::Fn {
+                    let field_name = if variant_def.ctor_kind() != Some(CtorKind::Fn) {
                         // Fields have names
                         Cow::from(variant_def.fields[field_index].name.as_str())
                     } else {
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 7822d924c01..03d833fbba8 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -938,7 +938,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         // that is understood elsewhere in the compiler as a method on
                         // `dyn Trait`.
                         // To get a `*mut RcBox<Self>`, we just keep unwrapping newtypes until
-                        // we get a value of a built-in pointer type
+                        // we get a value of a built-in pointer type.
+                        //
+                        // This is also relevant for `Pin<&mut Self>`, where we need to peel the `Pin`.
                         'descend_newtypes: while !op.layout.ty.is_unsafe_ptr()
                             && !op.layout.ty.is_region_ptr()
                         {
@@ -980,13 +982,29 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         continue;
                     }
                     Immediate(_) => {
-                        let ty::Ref(_, ty, _) = op.layout.ty.kind() else {
-                            span_bug!(span, "can't codegen a virtual call on {:#?}", op);
-                        };
-                        if !ty.is_dyn_star() {
+                        // See comment above explaining why we peel these newtypes
+                        'descend_newtypes: while !op.layout.ty.is_unsafe_ptr()
+                            && !op.layout.ty.is_region_ptr()
+                        {
+                            for i in 0..op.layout.fields.count() {
+                                let field = op.extract_field(bx, i);
+                                if !field.layout.is_zst() {
+                                    // we found the one non-zero-sized field that is allowed
+                                    // now find *its* non-zero-sized field, or stop if it's a
+                                    // pointer
+                                    op = field;
+                                    continue 'descend_newtypes;
+                                }
+                            }
+
+                            span_bug!(span, "receiver has no non-zero-sized fields {:?}", op);
+                        }
+
+                        // Make sure that we've actually unwrapped the rcvr down
+                        // to a pointer or ref to `dyn* Trait`.
+                        if !op.layout.ty.builtin_deref(true).unwrap().ty.is_dyn_star() {
                             span_bug!(span, "can't codegen a virtual call on {:#?}", op);
                         }
-                        // FIXME(dyn-star): Make sure this is done on a &dyn* receiver
                         let place = op.deref(bx.cx());
                         let data_ptr = place.project_field(bx, 0);
                         let meta_ptr = place.project_field(bx, 1);
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 002aaf0db13..301683e8e85 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -215,6 +215,7 @@ const HEXAGON_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
 const POWERPC_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     // tidy-alphabetical-start
     ("altivec", Some(sym::powerpc_target_feature)),
+    ("power10-vector", Some(sym::powerpc_target_feature)),
     ("power8-altivec", Some(sym::powerpc_target_feature)),
     ("power8-vector", Some(sym::powerpc_target_feature)),
     ("power9-altivec", Some(sym::powerpc_target_feature)),
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 36956f5dd6d..4564a6c4f2f 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -449,8 +449,17 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
             | Rvalue::CopyForDeref(..)
             | Rvalue::Repeat(..)
             | Rvalue::Discriminant(..)
-            | Rvalue::Len(_)
-            | Rvalue::Aggregate(..) => {}
+            | Rvalue::Len(_) => {}
+
+            Rvalue::Aggregate(ref kind, ..) => {
+                if let AggregateKind::Generator(def_id, ..) = kind.as_ref() {
+                    if let Some(generator_kind) = self.tcx.generator_kind(def_id.to_def_id()) {
+                        if matches!(generator_kind, hir::GeneratorKind::Async(..)) {
+                            self.check_op(ops::Generator(generator_kind));
+                        }
+                    }
+                }
+            }
 
             Rvalue::Ref(_, kind @ BorrowKind::Mut { .. }, ref place)
             | Rvalue::Ref(_, kind @ BorrowKind::Unique, ref place) => {
@@ -889,14 +898,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                     return;
                 }
 
-                // `async` blocks get lowered to `std::future::from_generator(/* a closure */)`.
-                let is_async_block = Some(callee) == tcx.lang_items().from_generator_fn();
-                if is_async_block {
-                    let kind = hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block);
-                    self.check_op(ops::Generator(kind));
-                    return;
-                }
-
                 if !tcx.is_const_fn_raw(callee) {
                     if !tcx.is_const_default_method(callee) {
                         // To get to here we must have already found a const impl for the
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 2d4afd0dc35..c62c6651587 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -1,7 +1,7 @@
 //! Concrete error types for all operations which may be invalid in a certain const context.
 
 use hir::def_id::LocalDefId;
-use hir::ConstContext;
+use hir::{ConstContext, LangItem};
 use rustc_errors::{
     error_code, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed,
 };
@@ -304,7 +304,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                     err.span_note(deref_target, "deref defined here");
                 }
 
-                diag_trait(&mut err, self_ty, tcx.lang_items().deref_trait().unwrap());
+                diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span)));
                 err
             }
             _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => {
diff --git a/compiler/rustc_const_eval/src/util/call_kind.rs b/compiler/rustc_const_eval/src/util/call_kind.rs
index 5446ccb1a47..b38a6c55138 100644
--- a/compiler/rustc_const_eval/src/util/call_kind.rs
+++ b/compiler/rustc_const_eval/src/util/call_kind.rs
@@ -3,7 +3,7 @@
 //! context.
 
 use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items;
+use rustc_hir::{lang_items, LangItem};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, AssocItemContainer, DefIdTree, Instance, ParamEnv, Ty, TyCtxt};
 use rustc_span::symbol::Ident;
@@ -26,7 +26,7 @@ impl CallDesugaringKind {
         match self {
             Self::ForLoopIntoIter => tcx.get_diagnostic_item(sym::IntoIterator).unwrap(),
             Self::QuestionBranch | Self::TryBlockFromOutput => {
-                tcx.lang_items().try_trait().unwrap()
+                tcx.require_lang_item(LangItem::Try, None)
             }
             Self::QuestionFromResidual => tcx.get_diagnostic_item(sym::FromResidual).unwrap(),
         }
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 8a712cec852..8e176efb2a9 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -318,7 +318,7 @@ fn run_compiler(
                             compiler.input(),
                             &*expanded_crate,
                             *ppm,
-                            compiler.output_file().as_ref().map(|p| &**p),
+                            compiler.output_file().as_deref(),
                         );
                         Ok(())
                     })?;
@@ -329,7 +329,7 @@ fn run_compiler(
                         compiler.input(),
                         &krate,
                         *ppm,
-                        compiler.output_file().as_ref().map(|p| &**p),
+                        compiler.output_file().as_deref(),
                     );
                 }
                 trace!("finished pretty-printing");
@@ -383,10 +383,7 @@ fn run_compiler(
                             &crate_name,
                             compiler.input(),
                             None,
-                            DumpHandler::new(
-                                compiler.output_dir().as_ref().map(|p| &**p),
-                                &crate_name,
-                            ),
+                            DumpHandler::new(compiler.output_dir().as_deref(), &crate_name),
                         )
                     });
                 }
diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl
index c292ae9b32a..d1e1fd54db9 100644
--- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl
@@ -275,7 +275,7 @@ metadata_crate_location_unknown_type =
     extern location for {$crate_name} is of an unknown type: {$path}
 
 metadata_lib_filename_form =
-    file name should be lib*.rlib or {dll_prefix}*.{dll_suffix}
+    file name should be lib*.rlib or {$dll_prefix}*{$dll_suffix}
 
 metadata_multiple_import_name_type =
     multiple `import_name_type` arguments in a single `#[link]` attribute
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index bc136aea44d..bf20c7431e4 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -248,7 +248,7 @@ pub trait Emitter: Translate {
         fluent_args: &FluentArgs<'_>,
     ) -> (MultiSpan, &'a [CodeSuggestion]) {
         let mut primary_span = diag.span.clone();
-        let suggestions = diag.suggestions.as_ref().map_or(&[][..], |suggestions| &suggestions[..]);
+        let suggestions = diag.suggestions.as_deref().unwrap_or(&[]);
         if let Some((sugg, rest)) = suggestions.split_first() {
             let msg = self.translate_message(&sugg.msg, fluent_args);
             if rest.is_empty() &&
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index f8747386c04..2be36a6eeb4 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -1044,13 +1044,24 @@ impl Handler {
     }
     pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
         if self.inner.borrow().has_errors_or_lint_errors() {
-            Some(ErrorGuaranteed(()))
+            Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
+        } else {
+            None
+        }
+    }
+    pub fn has_errors_or_delayed_span_bugs(&self) -> Option<ErrorGuaranteed> {
+        if self.inner.borrow().has_errors_or_delayed_span_bugs() {
+            Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
         } else {
             None
         }
     }
-    pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
-        self.inner.borrow().has_errors_or_delayed_span_bugs()
+    pub fn is_compilation_going_to_fail(&self) -> Option<ErrorGuaranteed> {
+        if self.inner.borrow().is_compilation_going_to_fail() {
+            Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
+        } else {
+            None
+        }
     }
 
     pub fn print_error_count(&self, registry: &Registry) {
@@ -1484,6 +1495,10 @@ impl HandlerInner {
         self.err_count() > 0 || self.lint_err_count > 0 || self.warn_count > 0
     }
 
+    fn is_compilation_going_to_fail(&self) -> bool {
+        self.has_errors() || self.lint_err_count > 0 || !self.delayed_span_bugs.is_empty()
+    }
+
     fn abort_if_errors(&mut self) {
         self.emit_stashed_diagnostics();
 
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 4ef4aad902c..149cf4ece37 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -28,8 +28,6 @@ pub enum CtorKind {
     Fn,
     /// Constructor constant automatically created by a unit struct/variant.
     Const,
-    /// Unusable name in value namespace created by a struct variant.
-    Fictive,
 }
 
 /// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`.
@@ -132,13 +130,9 @@ impl DefKind {
             DefKind::Variant => "variant",
             DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant",
             DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => "unit variant",
-            DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive) => "struct variant",
             DefKind::Struct => "struct",
             DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct",
             DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct",
-            DefKind::Ctor(CtorOf::Struct, CtorKind::Fictive) => {
-                panic!("impossible struct constructor")
-            }
             DefKind::OpaqueTy => "opaque type",
             DefKind::ImplTraitPlaceholder => "opaque type in trait",
             DefKind::TyAlias => "type alias",
@@ -562,19 +556,11 @@ impl<T> PerNS<Option<T>> {
 }
 
 impl CtorKind {
-    pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
-        match *vdata {
-            ast::VariantData::Tuple(..) => CtorKind::Fn,
-            ast::VariantData::Unit(..) => CtorKind::Const,
-            ast::VariantData::Struct(..) => CtorKind::Fictive,
-        }
-    }
-
-    pub fn from_hir(vdata: &hir::VariantData<'_>) -> CtorKind {
+    pub fn from_ast(vdata: &ast::VariantData) -> Option<(CtorKind, NodeId)> {
         match *vdata {
-            hir::VariantData::Tuple(..) => CtorKind::Fn,
-            hir::VariantData::Unit(..) => CtorKind::Const,
-            hir::VariantData::Struct(..) => CtorKind::Fictive,
+            ast::VariantData::Tuple(_, node_id) => Some((CtorKind::Fn, node_id)),
+            ast::VariantData::Unit(node_id) => Some((CtorKind::Const, node_id)),
+            ast::VariantData::Struct(..) => None,
         }
     }
 }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index e0a38645065..473a04f33a9 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2913,20 +2913,29 @@ impl<'hir> VariantData<'hir> {
         }
     }
 
-    /// Return the `LocalDefId` of this variant's constructor, if it has one.
-    pub fn ctor_def_id(&self) -> Option<LocalDefId> {
+    pub fn ctor(&self) -> Option<(CtorKind, HirId, LocalDefId)> {
         match *self {
-            VariantData::Struct(_, _) => None,
-            VariantData::Tuple(_, _, def_id) | VariantData::Unit(_, def_id) => Some(def_id),
+            VariantData::Tuple(_, hir_id, def_id) => Some((CtorKind::Fn, hir_id, def_id)),
+            VariantData::Unit(hir_id, def_id) => Some((CtorKind::Const, hir_id, def_id)),
+            VariantData::Struct(..) => None,
         }
     }
 
+    #[inline]
+    pub fn ctor_kind(&self) -> Option<CtorKind> {
+        self.ctor().map(|(kind, ..)| kind)
+    }
+
     /// Return the `HirId` of this variant's constructor, if it has one.
+    #[inline]
     pub fn ctor_hir_id(&self) -> Option<HirId> {
-        match *self {
-            VariantData::Struct(_, _) => None,
-            VariantData::Tuple(_, hir_id, _) | VariantData::Unit(hir_id, _) => Some(hir_id),
-        }
+        self.ctor().map(|(_, hir_id, _)| hir_id)
+    }
+
+    /// Return the `LocalDefId` of this variant's constructor, if it has one.
+    #[inline]
+    pub fn ctor_def_id(&self) -> Option<LocalDefId> {
+        self.ctor().map(|(.., def_id)| def_id)
     }
 }
 
@@ -3585,9 +3594,16 @@ mod size_asserts {
     static_assert_size!(Res, 12);
     static_assert_size!(Stmt<'_>, 32);
     static_assert_size!(StmtKind<'_>, 16);
+    // tidy-alphabetical-end
+    // FIXME: move the tidy directive to the end after the next bootstrap bump
+    #[cfg(bootstrap)]
     static_assert_size!(TraitItem<'_>, 88);
+    #[cfg(not(bootstrap))]
+    static_assert_size!(TraitItem<'_>, 80);
+    #[cfg(bootstrap)]
     static_assert_size!(TraitItemKind<'_>, 48);
+    #[cfg(not(bootstrap))]
+    static_assert_size!(TraitItemKind<'_>, 40);
     static_assert_size!(Ty<'_>, 48);
     static_assert_size!(TyKind<'_>, 32);
-    // tidy-alphabetical-end
 }
diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs
index 752f760ea97..33f02a115ef 100644
--- a/compiler/rustc_hir/src/hir_id.rs
+++ b/compiler/rustc_hir/src/hir_id.rs
@@ -1,4 +1,4 @@
-use crate::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
+use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_ID};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 use rustc_span::{def_id::DefPathHash, HashStableContext};
 use std::fmt;
@@ -22,6 +22,18 @@ impl OwnerId {
     }
 }
 
+impl rustc_index::vec::Idx for OwnerId {
+    #[inline]
+    fn new(idx: usize) -> Self {
+        OwnerId { def_id: LocalDefId { local_def_index: DefIndex::from_usize(idx) } }
+    }
+
+    #[inline]
+    fn index(self) -> usize {
+        self.def_id.local_def_index.as_usize()
+    }
+}
+
 impl<CTX: HashStableContext> HashStable<CTX> for OwnerId {
     #[inline]
     fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index b68dd25996b..038509031b1 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -280,10 +280,14 @@ language_item_table! {
 
     PointerSized,            sym::pointer_sized,       pointer_sized,              Target::Trait,          GenericRequirement::Exact(0);
 
+    Poll,                    sym::Poll,                poll,                       Target::Enum,           GenericRequirement::None;
     PollReady,               sym::Ready,               poll_ready_variant,         Target::Variant,        GenericRequirement::None;
     PollPending,             sym::Pending,             poll_pending_variant,       Target::Variant,        GenericRequirement::None;
 
-    FromGenerator,           sym::from_generator,      from_generator_fn,          Target::Fn,             GenericRequirement::None;
+    // FIXME(swatinem): the following lang items are used for async lowering and
+    // should become obsolete eventually.
+    ResumeTy,                sym::ResumeTy,            resume_ty,                  Target::Struct,         GenericRequirement::None;
+    IdentityFuture,          sym::identity_future,     identity_future_fn,         Target::Fn,             GenericRequirement::None;
     GetContext,              sym::get_context,         get_context_fn,             Target::Fn,             GenericRequirement::None;
 
     FuturePoll,              sym::poll,                future_poll_fn,             Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 33b9c61993a..069b405423c 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1165,7 +1165,7 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
     }
 
     if def.repr().int.is_none() {
-        let is_unit = |var: &ty::VariantDef| matches!(var.ctor_kind, CtorKind::Const);
+        let is_unit = |var: &ty::VariantDef| matches!(var.ctor_kind(), Some(CtorKind::Const));
         let has_disr = |var: &ty::VariantDef| matches!(var.discr, ty::VariantDiscr::Explicit(_));
 
         let has_non_units = def.variants().iter().any(|var| !is_unit(var));
diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs
index e68df228c6b..de386e2d135 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_method.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs
@@ -14,10 +14,8 @@ use rustc_infer::traits::util;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::util::ExplicitSelf;
 use rustc_middle::ty::{
-    self, AssocItem, DefIdTree, TraitRef, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable,
-    TypeVisitable,
+    self, DefIdTree, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
 };
-use rustc_middle::ty::{FnSig, InternalSubsts};
 use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
 use rustc_span::Span;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
@@ -51,11 +49,11 @@ pub(crate) fn compare_impl_method<'tcx>(
         return;
     }
 
-    if let Err(_) = compare_number_of_generics(tcx, impl_m, impl_m_span, trait_m, trait_item_span) {
+    if let Err(_) = compare_number_of_generics(tcx, impl_m, trait_m, trait_item_span, false) {
         return;
     }
 
-    if let Err(_) = compare_generic_param_kinds(tcx, impl_m, trait_m) {
+    if let Err(_) = compare_generic_param_kinds(tcx, impl_m, trait_m, false) {
         return;
     }
 
@@ -144,9 +142,9 @@ pub(crate) fn compare_impl_method<'tcx>(
 #[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))]
 fn compare_predicate_entailment<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_m: &AssocItem,
+    impl_m: &ty::AssocItem,
     impl_m_span: Span,
-    trait_m: &AssocItem,
+    trait_m: &ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
     let trait_to_impl_substs = impl_trait_ref.substs;
@@ -157,8 +155,7 @@ fn compare_predicate_entailment<'tcx>(
     // FIXME(@lcnr): remove that after removing `cause.body_id` from
     // obligations.
     let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
-    // We sometimes modify the span further down.
-    let mut cause = ObligationCause::new(
+    let cause = ObligationCause::new(
         impl_m_span,
         impl_m_hir_id,
         ObligationCauseCode::CompareImplItemObligation {
@@ -221,14 +218,11 @@ fn compare_predicate_entailment<'tcx>(
 
     debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
 
-    let mut selcx = traits::SelectionContext::new(&infcx);
     let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
     for (predicate, span) in iter::zip(impl_m_own_bounds.predicates, impl_m_own_bounds.spans) {
         let normalize_cause = traits::ObligationCause::misc(span, impl_m_hir_id);
-        let traits::Normalized { value: predicate, obligations } =
-            traits::normalize(&mut selcx, param_env, normalize_cause, predicate);
+        let predicate = ocx.normalize(normalize_cause, param_env, predicate);
 
-        ocx.register_obligations(obligations);
         let cause = ObligationCause::new(
             span,
             impl_m_hir_id,
@@ -291,30 +285,19 @@ fn compare_predicate_entailment<'tcx>(
     // type would be more appropriate. In other places we have a `Vec<Span>`
     // corresponding to their `Vec<Predicate>`, but we don't have that here.
     // Fixing this would improve the output of test `issue-83765.rs`.
-    let mut result = ocx.sup(&cause, param_env, trait_fty, impl_fty);
-
-    // HACK(RPITIT): #101614. When we are trying to infer the hidden types for
-    // RPITITs, we need to equate the output tys instead of just subtyping. If
-    // we just use `sup` above, we'll end up `&'static str <: _#1t`, which causes
-    // us to infer `_#1t = #'_#2r str`, where `'_#2r` is unconstrained, which gets
-    // fixed up to `ReEmpty`, and which is certainly not what we want.
-    if trait_fty.has_infer_types() {
-        result =
-            result.and_then(|()| ocx.eq(&cause, param_env, trait_sig.output(), impl_sig.output()));
-    }
+    let result = ocx.sup(&cause, param_env, trait_fty, impl_fty);
 
     if let Err(terr) = result {
         debug!(?terr, "sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
 
         let emitted = report_trait_method_mismatch(
-            tcx,
-            &mut cause,
             &infcx,
+            cause,
             terr,
             (trait_m, trait_fty),
             (impl_m, impl_fty),
-            &trait_sig,
-            &impl_trait_ref,
+            trait_sig,
+            impl_trait_ref,
         );
         return Err(emitted);
     }
@@ -352,11 +335,15 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
     let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap();
     let param_env = tcx.param_env(def_id);
 
+    // First, check a few of the same thing as `compare_impl_method`, just so we don't ICE during substitutions later.
+    compare_number_of_generics(tcx, impl_m, trait_m, tcx.hir().span_if_local(impl_m.def_id), true)?;
+    compare_generic_param_kinds(tcx, impl_m, trait_m, true)?;
+
     let trait_to_impl_substs = impl_trait_ref.substs;
 
     let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
     let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
-    let mut cause = ObligationCause::new(
+    let cause = ObligationCause::new(
         return_span,
         impl_m_hir_id,
         ObligationCauseCode::CompareImplItemObligation {
@@ -376,6 +363,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
     let infcx = &tcx.infer_ctxt().build();
     let ocx = ObligationCtxt::new(infcx);
 
+    // Normalize the impl signature with fresh variables for lifetime inference.
     let norm_cause = ObligationCause::misc(return_span, impl_m_hir_id);
     let impl_sig = ocx.normalize(
         norm_cause.clone(),
@@ -388,6 +376,10 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
     );
     let impl_return_ty = impl_sig.output();
 
+    // Normalize the trait signature with liberated bound vars, passing it through
+    // the ImplTraitInTraitCollector, which gathers all of the RPITITs and replaces
+    // them with inference variables.
+    // We will use these inference variables to collect the hidden types of RPITITs.
     let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_hir_id);
     let unnormalized_trait_sig = tcx
         .liberate_late_bound_regions(
@@ -448,14 +440,13 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
             // emit an error now because `compare_predicate_entailment` will not report the error
             // when normalization fails.
             let emitted = report_trait_method_mismatch(
-                tcx,
-                &mut cause,
                 infcx,
+                cause,
                 terr,
                 (trait_m, trait_fty),
                 (impl_m, impl_fty),
-                &trait_sig,
-                &impl_trait_ref,
+                trait_sig,
+                impl_trait_ref,
             );
             return Err(emitted);
         }
@@ -625,23 +616,21 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
 }
 
 fn report_trait_method_mismatch<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    cause: &mut ObligationCause<'tcx>,
     infcx: &InferCtxt<'tcx>,
+    mut cause: ObligationCause<'tcx>,
     terr: TypeError<'tcx>,
-    (trait_m, trait_fty): (&AssocItem, Ty<'tcx>),
-    (impl_m, impl_fty): (&AssocItem, Ty<'tcx>),
-    trait_sig: &FnSig<'tcx>,
-    impl_trait_ref: &TraitRef<'tcx>,
+    (trait_m, trait_fty): (&ty::AssocItem, Ty<'tcx>),
+    (impl_m, impl_fty): (&ty::AssocItem, Ty<'tcx>),
+    trait_sig: ty::FnSig<'tcx>,
+    impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> ErrorGuaranteed {
+    let tcx = infcx.tcx;
     let (impl_err_span, trait_err_span) =
         extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m);
 
-    cause.span = impl_err_span;
-
     let mut diag = struct_span_err!(
         tcx.sess,
-        cause.span(),
+        impl_err_span,
         E0053,
         "method `{}` has an incompatible type for trait",
         trait_m.name
@@ -712,6 +701,7 @@ fn report_trait_method_mismatch<'tcx>(
         _ => {}
     }
 
+    cause.span = impl_err_span;
     infcx.err_ctxt().note_type_err(
         &mut diag,
         &cause,
@@ -922,9 +912,9 @@ fn compare_self_type<'tcx>(
 fn compare_number_of_generics<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_: &ty::AssocItem,
-    _impl_span: Span,
     trait_: &ty::AssocItem,
     trait_span: Option<Span>,
+    delay: bool,
 ) -> Result<(), ErrorGuaranteed> {
     let trait_own_counts = tcx.generics_of(trait_.def_id).own_counts();
     let impl_own_counts = tcx.generics_of(impl_.def_id).own_counts();
@@ -1054,7 +1044,7 @@ fn compare_number_of_generics<'tcx>(
                 err.span_label(*span, "`impl Trait` introduces an implicit type parameter");
             }
 
-            let reported = err.emit();
+            let reported = err.emit_unless(delay);
             err_occurred = Some(reported);
         }
     }
@@ -1306,6 +1296,7 @@ fn compare_generic_param_kinds<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_item: &ty::AssocItem,
     trait_item: &ty::AssocItem,
+    delay: bool,
 ) -> Result<(), ErrorGuaranteed> {
     assert_eq!(impl_item.kind, trait_item.kind);
 
@@ -1363,7 +1354,7 @@ fn compare_generic_param_kinds<'tcx>(
             err.span_label(impl_header_span, "");
             err.span_label(param_impl_span, make_param_message("found", param_impl));
 
-            let reported = err.emit();
+            let reported = err.emit_unless(delay);
             return Err(reported);
         }
     }
@@ -1489,9 +1480,9 @@ pub(crate) fn compare_ty_impl<'tcx>(
     debug!("compare_impl_type(impl_trait_ref={:?})", impl_trait_ref);
 
     let _: Result<(), ErrorGuaranteed> = (|| {
-        compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?;
+        compare_number_of_generics(tcx, impl_ty, trait_ty, trait_item_span, false)?;
 
-        compare_generic_param_kinds(tcx, impl_ty, trait_ty)?;
+        compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
 
         let sp = tcx.def_span(impl_ty.def_id);
         compare_type_predicate_entailment(tcx, impl_ty, sp, trait_ty, impl_trait_ref)?;
@@ -1561,14 +1552,11 @@ fn compare_type_predicate_entailment<'tcx>(
 
     debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds());
 
-    let mut selcx = traits::SelectionContext::new(&infcx);
-
     assert_eq!(impl_ty_own_bounds.predicates.len(), impl_ty_own_bounds.spans.len());
     for (span, predicate) in std::iter::zip(impl_ty_own_bounds.spans, impl_ty_own_bounds.predicates)
     {
         let cause = ObligationCause::misc(span, impl_ty_hir_id);
-        let traits::Normalized { value: predicate, obligations } =
-            traits::normalize(&mut selcx, param_env, cause, predicate);
+        let predicate = ocx.normalize(cause, param_env, predicate);
 
         let cause = ObligationCause::new(
             span,
@@ -1579,7 +1567,6 @@ fn compare_type_predicate_entailment<'tcx>(
                 kind: impl_ty.kind,
             },
         );
-        ocx.register_obligations(obligations);
         ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
     }
 
@@ -1762,7 +1749,6 @@ pub fn check_type_bounds<'tcx>(
     let assumed_wf_types =
         ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty.def_id.expect_local());
 
-    let mut selcx = traits::SelectionContext::new(&infcx);
     let normalize_cause = ObligationCause::new(
         impl_ty_span,
         impl_ty_hir_id,
@@ -1791,16 +1777,11 @@ pub fn check_type_bounds<'tcx>(
     debug!("check_type_bounds: item_bounds={:?}", obligations);
 
     for mut obligation in util::elaborate_obligations(tcx, obligations) {
-        let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize(
-            &mut selcx,
-            normalize_param_env,
-            normalize_cause.clone(),
-            obligation.predicate,
-        );
+        let normalized_predicate =
+            ocx.normalize(normalize_cause.clone(), normalize_param_env, obligation.predicate);
         debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
         obligation.predicate = normalized_predicate;
 
-        ocx.register_obligations(obligations);
         ocx.register_obligation(obligation);
     }
     // Check that all obligations are satisfied by the implementation's
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index a74016e220e..e0b465bab16 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -244,6 +244,10 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
         self.tcx
     }
 
+    fn intercrate(&self) -> bool {
+        false
+    }
+
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.param_env
     }
@@ -256,6 +260,10 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
         true
     }
 
+    fn mark_ambiguous(&mut self) {
+        bug!()
+    }
+
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _: ty::Variance,
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index b2c9e7389b0..11661215ae1 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -114,7 +114,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
                     traits::ObligationCause::dummy_with_span(field_ty_span),
                     param_env,
                     ty,
-                    tcx.lang_items().copy_trait().unwrap(),
+                    tcx.require_lang_item(LangItem::Copy, Some(span)),
                 ) {
                     let error_predicate = error.obligation.predicate;
                     // Only note if it's not the root obligation, otherwise it's trivial and
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 71c932d747b..d66b6585fb6 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -5,7 +5,6 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{struct_span_err, DelayDm};
 use rustc_errors::{Diagnostic, ErrorGuaranteed};
 use rustc_hir as hir;
-use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::util::IgnoreRegions;
 use rustc_middle::ty::{
@@ -47,58 +46,6 @@ fn do_orphan_check_impl<'tcx>(
     let sp = tcx.def_span(def_id);
     let tr = impl_.of_trait.as_ref().unwrap();
 
-    // Ensure no opaque types are present in this impl header. See issues #76202 and #86411 for examples,
-    // and #84660 where it would otherwise allow unsoundness.
-    if trait_ref.has_opaque_types() {
-        trace!("{:#?}", item);
-        // First we find the opaque type in question.
-        for ty in trait_ref.substs {
-            for ty in ty.walk() {
-                let ty::subst::GenericArgKind::Type(ty) = ty.unpack() else { continue };
-                let ty::Opaque(def_id, _) = *ty.kind() else { continue };
-                trace!(?def_id);
-
-                // Then we search for mentions of the opaque type's type alias in the HIR
-                struct SpanFinder<'tcx> {
-                    sp: Span,
-                    def_id: DefId,
-                    tcx: TyCtxt<'tcx>,
-                }
-                impl<'v, 'tcx> hir::intravisit::Visitor<'v> for SpanFinder<'tcx> {
-                    #[instrument(level = "trace", skip(self, _id))]
-                    fn visit_path(&mut self, path: &'v hir::Path<'v>, _id: hir::HirId) {
-                        // You can't mention an opaque type directly, so we look for type aliases
-                        if let hir::def::Res::Def(hir::def::DefKind::TyAlias, def_id) = path.res {
-                            // And check if that type alias's type contains the opaque type we're looking for
-                            for arg in self.tcx.type_of(def_id).walk() {
-                                if let GenericArgKind::Type(ty) = arg.unpack() {
-                                    if let ty::Opaque(def_id, _) = *ty.kind() {
-                                        if def_id == self.def_id {
-                                            // Finally we update the span to the mention of the type alias
-                                            self.sp = path.span;
-                                            return;
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                        hir::intravisit::walk_path(self, path)
-                    }
-                }
-
-                let mut visitor = SpanFinder { sp, def_id, tcx };
-                hir::intravisit::walk_item(&mut visitor, item);
-                let reported = tcx
-                    .sess
-                    .struct_span_err(visitor.sp, "cannot implement trait on type alias impl trait")
-                    .span_note(tcx.def_span(def_id), "type alias impl trait defined here")
-                    .emit();
-                return Err(reported);
-            }
-        }
-        span_bug!(sp, "opaque type not found, but `has_opaque_types` is set")
-    }
-
     match traits::orphan_check(tcx, item.owner_id.to_def_id()) {
         Ok(()) => {}
         Err(err) => emit_orphan_check_error(
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index a738ee4a148..4c1d95a452d 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -24,7 +24,6 @@ use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
-use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
@@ -34,7 +33,6 @@ use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}
 use rustc_middle::mir::mono::Linkage;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::ReprOptions;
 use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, IsSuggestable, Ty, TyCtxt};
 use rustc_session::lint;
 use rustc_session::parse::feature_err;
@@ -794,7 +792,7 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
 
         // Convert the ctor, if any. This also registers the variant as
         // an item.
-        if let Some(ctor_def_id) = variant.ctor_def_id {
+        if let Some(ctor_def_id) = variant.ctor_def_id() {
             convert_variant_ctor(tcx, ctor_def_id.expect_local());
         }
     }
@@ -803,7 +801,6 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
 fn convert_variant(
     tcx: TyCtxt<'_>,
     variant_did: Option<LocalDefId>,
-    ctor_did: Option<LocalDefId>,
     ident: Ident,
     discr: ty::VariantDiscr,
     def: &hir::VariantData<'_>,
@@ -840,10 +837,9 @@ fn convert_variant(
     ty::VariantDef::new(
         ident.name,
         variant_did.map(LocalDefId::to_def_id),
-        ctor_did.map(LocalDefId::to_def_id),
+        def.ctor().map(|(kind, _, def_id)| (kind, def_id.to_def_id())),
         discr,
         fields,
-        CtorKind::from_hir(def),
         adt_kind,
         parent_did.to_def_id(),
         recovered,
@@ -863,7 +859,7 @@ fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {
         bug!();
     };
 
-    let repr = ReprOptions::new(tcx, def_id.to_def_id());
+    let repr = tcx.repr_options_of_def(def_id.to_def_id());
     let (kind, variants) = match item.kind {
         ItemKind::Enum(ref def, _) => {
             let mut distance_from_explicit = 0;
@@ -882,7 +878,6 @@ fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {
                     convert_variant(
                         tcx,
                         Some(v.def_id),
-                        v.data.ctor_def_id(),
                         v.ident,
                         discr,
                         &v.data,
@@ -894,35 +889,23 @@ fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {
 
             (AdtKind::Enum, variants)
         }
-        ItemKind::Struct(ref def, _) => {
-            let variants = std::iter::once(convert_variant(
-                tcx,
-                None,
-                def.ctor_def_id(),
-                item.ident,
-                ty::VariantDiscr::Relative(0),
-                def,
-                AdtKind::Struct,
-                def_id,
-            ))
-            .collect();
-
-            (AdtKind::Struct, variants)
-        }
-        ItemKind::Union(ref def, _) => {
+        ItemKind::Struct(ref def, _) | ItemKind::Union(ref def, _) => {
+            let adt_kind = match item.kind {
+                ItemKind::Struct(..) => AdtKind::Struct,
+                _ => AdtKind::Union,
+            };
             let variants = std::iter::once(convert_variant(
                 tcx,
                 None,
-                def.ctor_def_id(),
                 item.ident,
                 ty::VariantDiscr::Relative(0),
                 def,
-                AdtKind::Union,
+                adt_kind,
                 def_id,
             ))
             .collect();
 
-            (AdtKind::Union, variants)
+            (adt_kind, variants)
         }
         _ => bug!(),
     };
@@ -1171,7 +1154,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
             compute_sig_of_foreign_fn_decl(tcx, def_id.to_def_id(), fn_decl, abi)
         }
 
-        Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor_hir_id().is_some() => {
+        Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
             let ty = tcx.type_of(tcx.hir().get_parent_item(hir_id));
             let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id));
             ty::Binder::dummy(tcx.mk_fn_sig(
@@ -2173,7 +2156,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
         .emit();
     }
     let meta_item_list = attr.meta_item_list();
-    let meta_item_list: Option<&[ast::NestedMetaItem]> = meta_item_list.as_ref().map(Vec::as_ref);
+    let meta_item_list = meta_item_list.as_deref();
     let sole_meta_list = match meta_item_list {
         Some([item]) => item.literal(),
         Some(_) => {
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index 55cca0cd2d7..bae43138b4d 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -517,6 +517,7 @@ fn trait_predicate_kind<'tcx>(
         | ty::PredicateKind::ClosureKind(..)
         | ty::PredicateKind::ConstEvaluatable(..)
         | ty::PredicateKind::ConstEquate(..)
+        | ty::PredicateKind::Ambiguous
         | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
index 7534482cce9..f0381353551 100644
--- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
@@ -59,6 +59,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
                     | ty::PredicateKind::Coerce(..)
                     | ty::PredicateKind::ConstEvaluatable(..)
                     | ty::PredicateKind::ConstEquate(..)
+                    | ty::PredicateKind::Ambiguous
                     | ty::PredicateKind::TypeWellFormedFromEnv(..) => (),
                 }
             }
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index eaf0310d57a..6ce0c18bf45 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -72,8 +72,8 @@ pub fn add_constraints_from_crate<'a, 'tcx>(
 
                 let adt = tcx.adt_def(def_id);
                 for variant in adt.variants() {
-                    if let Some(ctor) = variant.ctor_def_id {
-                        constraint_cx.build_constraints_for_item(ctor.expect_local());
+                    if let Some(ctor_def_id) = variant.ctor_def_id() {
+                        constraint_cx.build_constraints_for_item(ctor_def_id.expect_local());
                     }
                 }
             }
diff --git a/compiler/rustc_hir_analysis/src/variance/terms.rs b/compiler/rustc_hir_analysis/src/variance/terms.rs
index 1f763011e06..58e8f474761 100644
--- a/compiler/rustc_hir_analysis/src/variance/terms.rs
+++ b/compiler/rustc_hir_analysis/src/variance/terms.rs
@@ -91,8 +91,8 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
 
                 let adt = tcx.adt_def(def_id);
                 for variant in adt.variants() {
-                    if let Some(ctor) = variant.ctor_def_id {
-                        terms_cx.add_inferreds_for_item(ctor.expect_local());
+                    if let Some(ctor_def_id) = variant.ctor_def_id() {
+                        terms_cx.add_inferreds_for_item(ctor_def_id.expect_local());
                     }
                 }
             }
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 302d512c71d..25b6cf4ef2e 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -6,7 +6,7 @@ use crate::type_error_struct;
 use rustc_ast::util::parser::PREC_POSTFIX;
 use rustc_errors::{struct_span_err, Applicability, Diagnostic, StashKey};
 use rustc_hir as hir;
-use rustc_hir::def::{self, Namespace, Res};
+use rustc_hir::def::{self, CtorKind, Namespace, Res};
 use rustc_hir::def_id::DefId;
 use rustc_infer::{
     infer,
@@ -30,7 +30,7 @@ use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::DefIdOrName;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 
-use std::iter;
+use std::{iter, slice};
 
 /// Checks that it is legal to call methods of the trait corresponding
 /// to `trait_id` (this only cares about the trait, not the specific
@@ -227,22 +227,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ] {
             let Some(trait_def_id) = opt_trait_def_id else { continue };
 
-            let opt_input_types = opt_arg_exprs.map(|arg_exprs| {
-                [self.tcx.mk_tup(arg_exprs.iter().map(|e| {
+            let opt_input_type = opt_arg_exprs.map(|arg_exprs| {
+                self.tcx.mk_tup(arg_exprs.iter().map(|e| {
                     self.next_ty_var(TypeVariableOrigin {
                         kind: TypeVariableOriginKind::TypeInference,
                         span: e.span,
                     })
-                }))]
+                }))
             });
-            let opt_input_types = opt_input_types.as_ref().map(AsRef::as_ref);
 
             if let Some(ok) = self.lookup_method_in_trait(
                 call_expr.span,
                 method_name,
                 trait_def_id,
                 adjusted_ty,
-                opt_input_types,
+                opt_input_type.as_ref().map(slice::from_ref),
             ) {
                 let method = self.register_infer_ok_obligations(ok);
                 let mut autoref = None;
@@ -595,7 +594,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         let mut unit_variant = None;
         if let hir::ExprKind::Path(qpath) = &callee_expr.kind
-            && let Res::Def(def::DefKind::Ctor(kind, def::CtorKind::Const), _)
+            && let Res::Def(def::DefKind::Ctor(kind, CtorKind::Const), _)
                 = self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
             // Only suggest removing parens if there are no arguments
             && arg_exprs.is_empty()
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index b9e90e47e50..2c24b9ef14e 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -56,10 +56,15 @@ pub(super) fn check_fn<'a, 'tcx>(
 
     fn_maybe_err(tcx, span, fn_sig.abi);
 
-    if body.generator_kind.is_some() && can_be_generator.is_some() {
-        let yield_ty = fcx
-            .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
-        fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
+    if let Some(kind) = body.generator_kind && can_be_generator.is_some() {
+        let yield_ty = if kind == hir::GeneratorKind::Gen {
+            let yield_ty = fcx
+                .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
+            fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
+            yield_ty
+        } else {
+            tcx.mk_unit()
+        };
 
         // Resume type defaults to `()` if the generator has no argument.
         let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| tcx.mk_unit());
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 43c7127b0d4..82784bb8a66 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -46,7 +46,7 @@ use rustc_hir::Expr;
 use rustc_hir_analysis::astconv::AstConv;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{Coercion, InferOk, InferResult};
-use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt};
+use rustc_infer::traits::Obligation;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
@@ -62,8 +62,7 @@ use rustc_span::{self, BytePos, DesugaringKind, Span};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
-use rustc_trait_selection::traits::TraitEngineExt as _;
-use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt};
 
 use smallvec::{smallvec, SmallVec};
 use std::ops::Deref;
@@ -589,7 +588,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             }
             _ => None,
         };
-        let coerce_source = reborrow.as_ref().map_or(source, |&(_, ref r)| r.target);
+        let coerce_source = reborrow.as_ref().map_or(source, |(_, r)| r.target);
 
         // Setup either a subtyping or a LUB relationship between
         // the `CoerceUnsized` target type and the expected type.
@@ -756,20 +755,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
         if let ty::Dynamic(a_data, _, _) = a.kind()
             && let ty::Dynamic(b_data, _, _) = b.kind()
+            && a_data.principal_def_id() == b_data.principal_def_id()
         {
-            if a_data.principal_def_id() == b_data.principal_def_id() {
-                return self.unify_and(a, b, |_| vec![]);
-            } else if !self.tcx().features().trait_upcasting {
-                let mut err = feature_err(
-                    &self.tcx.sess.parse_sess,
-                    sym::trait_upcasting,
-                    self.cause.span,
-                    &format!(
-                        "cannot cast `{a}` to `{b}`, trait upcasting coercion is experimental"
-                    ),
-                );
-                err.emit();
-            }
+            return self.unify_and(a, b, |_| vec![]);
         }
 
         // Check the obligations of the cast -- for example, when casting
@@ -797,19 +785,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             ])
             .collect();
 
-        // Enforce that the type is `usize`/pointer-sized. For now, only those
-        // can be coerced to `dyn*`, except for `dyn* -> dyn*` upcasts.
-        if !a.is_dyn_star() {
-            obligations.push(Obligation::new(
-                self.tcx,
-                self.cause.clone(),
-                self.param_env,
-                ty::Binder::dummy(
-                    self.tcx.at(self.cause.span).mk_trait_ref(hir::LangItem::PointerSized, [a]),
-                )
-                .to_poly_trait_predicate(),
-            ));
-        }
+        // Enforce that the type is `usize`/pointer-sized.
+        obligations.push(Obligation::new(
+            self.tcx,
+            self.cause.clone(),
+            self.param_env,
+            ty::Binder::dummy(
+                self.tcx.at(self.cause.span).mk_trait_ref(hir::LangItem::PointerSized, [a]),
+            )
+            .to_poly_trait_predicate(),
+        ));
 
         Ok(InferOk {
             value: (vec![Adjustment { kind: Adjust::DynStar, target: b }], b),
@@ -1055,9 +1040,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let Ok(ok) = coerce.coerce(source, target) else {
                 return false;
             };
-            let mut fcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.tcx);
-            fcx.register_predicate_obligations(self, ok.obligations);
-            fcx.select_where_possible(&self).is_empty()
+            let ocx = ObligationCtxt::new_in_snapshot(self);
+            ocx.register_obligations(ok.obligations);
+            ocx.select_where_possible().is_empty()
         })
     }
 
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 5a34ab40174..934d1240442 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -2,6 +2,7 @@ use crate::FnCtxt;
 use rustc_ast::util::parser::PREC_POSTFIX;
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
+use rustc_hir::def::CtorKind;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{is_range_literal, Node};
 use rustc_infer::infer::InferOk;
@@ -404,27 +405,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         if let Some(path) = variant_path.strip_prefix("std::prelude::")
                             && let Some((_, path)) = path.split_once("::")
                         {
-                            return Some((path.to_string(), variant.ctor_kind, sole_field.name, note_about_variant_field_privacy));
+                            return Some((path.to_string(), variant.ctor_kind(), sole_field.name, note_about_variant_field_privacy));
                         }
-                        Some((variant_path, variant.ctor_kind, sole_field.name, note_about_variant_field_privacy))
+                        Some((variant_path, variant.ctor_kind(), sole_field.name, note_about_variant_field_privacy))
                     } else {
                         None
                     }
                 })
                 .collect();
 
-            let suggestions_for = |variant: &_, ctor, field_name| {
+            let suggestions_for = |variant: &_, ctor_kind, field_name| {
                 let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
                     Some(ident) => format!("{ident}: "),
                     None => String::new(),
                 };
 
-                let (open, close) = match ctor {
-                    hir::def::CtorKind::Fn => ("(".to_owned(), ")"),
-                    hir::def::CtorKind::Fictive => (format!(" {{ {field_name}: "), " }"),
+                let (open, close) = match ctor_kind {
+                    Some(CtorKind::Fn) => ("(".to_owned(), ")"),
+                    None => (format!(" {{ {field_name}: "), " }"),
 
                     // unit variants don't have fields
-                    hir::def::CtorKind::Const => unreachable!(),
+                    Some(CtorKind::Const) => unreachable!(),
                 };
 
                 // Suggest constructor as deep into the block tree as possible.
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index de30bfe6923..91f65b8c0f2 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -533,8 +533,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.set_tainted_by_errors(e);
                 tcx.ty_error_with_guaranteed(e)
             }
-            Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) => {
-                let e = report_unexpected_variant_res(tcx, res, qpath, expr.span);
+            Res::Def(DefKind::Variant, _) => {
+                let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, "E0533", "value");
                 tcx.ty_error_with_guaranteed(e)
             }
             _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
@@ -1118,7 +1118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let lhs_deref_ty_is_sized = self
                     .infcx
                     .type_implements_trait(
-                        self.tcx.lang_items().sized_trait().unwrap(),
+                        self.tcx.require_lang_item(LangItem::Sized, None),
                         [lhs_deref_ty],
                         self.param_env,
                     )
@@ -2024,8 +2024,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         );
 
         let variant_ident_span = self.tcx.def_ident_span(variant.def_id).unwrap();
-        match variant.ctor_kind {
-            CtorKind::Fn => match ty.kind() {
+        match variant.ctor_kind() {
+            Some(CtorKind::Fn) => match ty.kind() {
                 ty::Adt(adt, ..) if adt.is_enum() => {
                     err.span_label(
                         variant_ident_span,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index b85a2325728..c7bfe99aa9a 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -702,6 +702,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // code is looking for a self type of an unresolved
                 // inference variable.
                 | ty::PredicateKind::ClosureKind(..)
+                | ty::PredicateKind::Ambiguous
                 | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
             },
         )
@@ -1164,11 +1165,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             match *ty.kind() {
                 ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
                     let variant = adt_def.non_enum_variant();
-                    let ctor_def_id = variant.ctor_def_id.unwrap();
-                    (
-                        Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id),
-                        Some(substs),
-                    )
+                    let (ctor_kind, ctor_def_id) = variant.ctor.unwrap();
+                    (Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id), Some(substs))
                 }
                 _ => {
                     let mut err = tcx.sess.struct_span_err(
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index a31ab9c8b23..5727a120390 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1734,14 +1734,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let hir = self.tcx.hir();
         let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; };
 
-        // Skip over mentioning async lang item
-        if Some(def_id) == self.tcx.lang_items().from_generator_fn()
-            && error.obligation.cause.span.desugaring_kind()
-                == Some(rustc_span::DesugaringKind::Async)
-        {
-            return false;
-        }
-
         let Some(unsubstituted_pred) =
             self.tcx.predicates_of(def_id).instantiate_identity(self.tcx).predicates.into_iter().nth(idx)
             else { return false; };
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
index a78b294181c..fd8ea1ad7bf 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
@@ -9,9 +9,10 @@ use hir::{
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_index::vec::IndexVec;
+use rustc_infer::infer::InferCtxt;
 use rustc_middle::{
     hir::map::Map,
-    ty::{TyCtxt, TypeckResults},
+    ty::{ParamEnv, TyCtxt, TypeVisitable, TypeckResults},
 };
 use std::mem::swap;
 
@@ -21,20 +22,29 @@ use std::mem::swap;
 /// The resulting structure still needs to be iterated to a fixed point, which
 /// can be done with propagate_to_fixpoint in cfg_propagate.
 pub(super) fn build_control_flow_graph<'tcx>(
-    hir: Map<'tcx>,
-    tcx: TyCtxt<'tcx>,
+    infcx: &InferCtxt<'tcx>,
     typeck_results: &TypeckResults<'tcx>,
+    param_env: ParamEnv<'tcx>,
     consumed_borrowed_places: ConsumedAndBorrowedPlaces,
     body: &'tcx Body<'tcx>,
     num_exprs: usize,
 ) -> (DropRangesBuilder, FxHashSet<HirId>) {
-    let mut drop_range_visitor =
-        DropRangeVisitor::new(hir, tcx, typeck_results, consumed_borrowed_places, num_exprs);
+    let mut drop_range_visitor = DropRangeVisitor::new(
+        infcx,
+        typeck_results,
+        param_env,
+        consumed_borrowed_places,
+        num_exprs,
+    );
     intravisit::walk_body(&mut drop_range_visitor, body);
 
     drop_range_visitor.drop_ranges.process_deferred_edges();
-    if let Some(filename) = &tcx.sess.opts.unstable_opts.dump_drop_tracking_cfg {
-        super::cfg_visualize::write_graph_to_file(&drop_range_visitor.drop_ranges, filename, tcx);
+    if let Some(filename) = &infcx.tcx.sess.opts.unstable_opts.dump_drop_tracking_cfg {
+        super::cfg_visualize::write_graph_to_file(
+            &drop_range_visitor.drop_ranges,
+            filename,
+            infcx.tcx,
+        );
     }
 
     (drop_range_visitor.drop_ranges, drop_range_visitor.places.borrowed_temporaries)
@@ -82,40 +92,44 @@ pub(super) fn build_control_flow_graph<'tcx>(
 /// ```
 
 struct DropRangeVisitor<'a, 'tcx> {
-    hir: Map<'tcx>,
+    typeck_results: &'a TypeckResults<'tcx>,
+    infcx: &'a InferCtxt<'tcx>,
+    param_env: ParamEnv<'tcx>,
     places: ConsumedAndBorrowedPlaces,
     drop_ranges: DropRangesBuilder,
     expr_index: PostOrderId,
-    tcx: TyCtxt<'tcx>,
-    typeck_results: &'a TypeckResults<'tcx>,
     label_stack: Vec<(Option<rustc_ast::Label>, PostOrderId)>,
 }
 
 impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
     fn new(
-        hir: Map<'tcx>,
-        tcx: TyCtxt<'tcx>,
+        infcx: &'a InferCtxt<'tcx>,
         typeck_results: &'a TypeckResults<'tcx>,
+        param_env: ParamEnv<'tcx>,
         places: ConsumedAndBorrowedPlaces,
         num_exprs: usize,
     ) -> Self {
         debug!("consumed_places: {:?}", places.consumed);
         let drop_ranges = DropRangesBuilder::new(
             places.consumed.iter().flat_map(|(_, places)| places.iter().cloned()),
-            hir,
+            infcx.tcx.hir(),
             num_exprs,
         );
         Self {
-            hir,
+            infcx,
+            typeck_results,
+            param_env,
             places,
             drop_ranges,
             expr_index: PostOrderId::from_u32(0),
-            typeck_results,
-            tcx,
             label_stack: vec![],
         }
     }
 
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+
     fn record_drop(&mut self, value: TrackedValue) {
         if self.places.borrowed.contains(&value) {
             debug!("not marking {:?} as dropped because it is borrowed at some point", value);
@@ -137,7 +151,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
             .map_or(vec![], |places| places.iter().cloned().collect());
         for place in places {
             trace!(?place, "consuming place");
-            for_each_consumable(self.hir, place, |value| self.record_drop(value));
+            for_each_consumable(self.tcx().hir(), place, |value| self.record_drop(value));
         }
     }
 
@@ -214,10 +228,15 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
     /// return.
     fn handle_uninhabited_return(&mut self, expr: &Expr<'tcx>) {
         let ty = self.typeck_results.expr_ty(expr);
-        let ty = self.tcx.erase_regions(ty);
-        let m = self.tcx.parent_module(expr.hir_id).to_def_id();
-        let param_env = self.tcx.param_env(m.expect_local());
-        if !ty.is_inhabited_from(self.tcx, m, param_env) {
+        let ty = self.infcx.resolve_vars_if_possible(ty);
+        if ty.has_non_region_infer() {
+            self.tcx()
+                .sess
+                .delay_span_bug(expr.span, format!("could not resolve infer vars in `{ty}`"));
+        }
+        let ty = self.tcx().erase_regions(ty);
+        let m = self.tcx().parent_module(expr.hir_id).to_def_id();
+        if !ty.is_inhabited_from(self.tcx(), m, self.param_env) {
             // This function will not return. We model this fact as an infinite loop.
             self.drop_ranges.add_control_edge(self.expr_index + 1, self.expr_index + 1);
         }
@@ -238,7 +257,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
         destination: hir::Destination,
     ) -> Result<HirId, LoopIdError> {
         destination.target_id.map(|target| {
-            let node = self.hir.get(target);
+            let node = self.tcx().hir().get(target);
             match node {
                 hir::Node::Expr(_) => target,
                 hir::Node::Block(b) => find_last_block_expression(b),
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
index 4f3bdfbe758..2abcadcc9ce 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
@@ -43,9 +43,9 @@ pub fn compute_drop_ranges<'a, 'tcx>(
         let typeck_results = &fcx.typeck_results.borrow();
         let num_exprs = fcx.tcx.region_scope_tree(def_id).body_expr_count(body.id()).unwrap_or(0);
         let (mut drop_ranges, borrowed_temporaries) = build_control_flow_graph(
-            fcx.tcx.hir(),
-            fcx.tcx,
+            &fcx,
             typeck_results,
+            fcx.param_env,
             consumed_borrowed_places,
             body,
             num_exprs,
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 334d6d0aa6c..5104b448023 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -53,9 +53,9 @@ use crate::check::check_fn;
 use crate::coercion::DynamicCoerceMany;
 use crate::gather_locals::GatherLocalsVisitor;
 use rustc_data_structures::unord::UnordSet;
-use rustc_errors::{struct_span_err, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{struct_span_err, DiagnosticId, ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
-use rustc_hir::def::Res;
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{HirIdMap, Node};
 use rustc_hir_analysis::astconv::AstConv;
@@ -433,15 +433,27 @@ fn report_unexpected_variant_res(
     res: Res,
     qpath: &hir::QPath<'_>,
     span: Span,
+    err_code: &str,
+    expected: &str,
 ) -> ErrorGuaranteed {
-    struct_span_err!(
-        tcx.sess,
+    let res_descr = match res {
+        Res::Def(DefKind::Variant, _) => "struct variant",
+        _ => res.descr(),
+    };
+    let path_str = rustc_hir_pretty::qpath_to_string(qpath);
+    let mut err = tcx.sess.struct_span_err_with_code(
         span,
-        E0533,
-        "expected unit struct, unit variant or constant, found {} `{}`",
-        res.descr(),
-        rustc_hir_pretty::qpath_to_string(qpath),
-    )
+        format!("expected {expected}, found {res_descr} `{path_str}`"),
+        DiagnosticId::Error(err_code.into()),
+    );
+    match res {
+        Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == "E0164" => {
+            let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html";
+            err.span_label(span, "`fn` calls are not allowed in patterns");
+            err.help(format!("for more information, visit {patterns_url}"))
+        }
+        _ => err.span_label(span, format!("not a {expected}")),
+    }
     .emit()
 }
 
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 37336edd1fd..9b1f0cff074 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -566,6 +566,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let tcx = self.tcx;
 
         // Check if we have an enum variant.
+        let mut struct_variant = None;
         if let ty::Adt(adt_def, _) = self_ty.kind() {
             if adt_def.is_enum() {
                 let variant_def = adt_def
@@ -573,16 +574,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .iter()
                     .find(|vd| tcx.hygienic_eq(method_name, vd.ident(tcx), adt_def.did()));
                 if let Some(variant_def) = variant_def {
-                    // Braced variants generate unusable names in value namespace (reserved for
-                    // possible future use), so variants resolved as associated items may refer to
-                    // them as well. It's ok to use the variant's id as a ctor id since an
-                    // error will be reported on any use of such resolution anyway.
-                    let ctor_def_id = variant_def.ctor_def_id.unwrap_or(variant_def.def_id);
-                    tcx.check_stability(ctor_def_id, Some(expr_id), span, Some(method_name.span));
-                    return Ok((
-                        DefKind::Ctor(CtorOf::Variant, variant_def.ctor_kind),
-                        ctor_def_id,
-                    ));
+                    if let Some((ctor_kind, ctor_def_id)) = variant_def.ctor {
+                        tcx.check_stability(
+                            ctor_def_id,
+                            Some(expr_id),
+                            span,
+                            Some(method_name.span),
+                        );
+                        return Ok((DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id));
+                    } else {
+                        struct_variant = Some((DefKind::Variant, variant_def.def_id));
+                    }
                 }
             }
         }
@@ -594,7 +596,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self_ty,
             expr_id,
             ProbeScope::TraitsInScope,
-        )?;
+        );
+        let pick = match (pick, struct_variant) {
+            // Fall back to a resolution that will produce an error later.
+            (Err(_), Some(res)) => return Ok(res),
+            (pick, _) => pick?,
+        };
 
         pick.maybe_emit_unstable_name_collision_hint(self.tcx, span, expr_id);
 
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 9d75ccad133..44c3edf06a8 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -803,6 +803,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 | ty::PredicateKind::TypeOutlives(..)
                 | ty::PredicateKind::ConstEvaluatable(..)
                 | ty::PredicateKind::ConstEquate(..)
+                | ty::PredicateKind::Ambiguous
                 | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
             }
         });
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 1d021f19104..2fe1b1d8999 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -853,8 +853,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.set_tainted_by_errors(e);
                 return tcx.ty_error_with_guaranteed(e);
             }
-            Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fictive | CtorKind::Fn), _) => {
-                let e = report_unexpected_variant_res(tcx, res, qpath, pat.span);
+            Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => {
+                let expected = "unit struct, unit variant or constant";
+                let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0533", expected);
                 return tcx.ty_error_with_guaranteed(e);
             }
             Res::SelfCtor(..)
@@ -1002,30 +1003,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         };
         let report_unexpected_res = |res: Res| {
-            let sm = tcx.sess.source_map();
-            let path_str = sm
-                .span_to_snippet(sm.span_until_char(pat.span, '('))
-                .map_or_else(|_| String::new(), |s| format!(" `{}`", s.trim_end()));
-            let msg = format!(
-                "expected tuple struct or tuple variant, found {}{}",
-                res.descr(),
-                path_str
-            );
-
-            let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{msg}");
-            match res {
-                Res::Def(DefKind::Fn | DefKind::AssocFn, _) => {
-                    err.span_label(pat.span, "`fn` calls are not allowed in patterns");
-                    err.help(
-                        "for more information, visit \
-                              https://doc.rust-lang.org/book/ch18-00-patterns.html",
-                    );
-                }
-                _ => {
-                    err.span_label(pat.span, "not a tuple variant or struct");
-                }
-            }
-            let e = err.emit();
+            let expected = "tuple struct or tuple variant";
+            let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0164", expected);
             on_error(e);
             e
         };
@@ -1481,8 +1460,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // if this is a tuple struct, then all field names will be numbers
         // so if any fields in a struct pattern use shorthand syntax, they will
         // be invalid identifiers (for example, Foo { 0, 1 }).
-        if let (CtorKind::Fn, PatKind::Struct(qpath, field_patterns, ..)) =
-            (variant.ctor_kind, &pat.kind)
+        if let (Some(CtorKind::Fn), PatKind::Struct(qpath, field_patterns, ..)) =
+            (variant.ctor_kind(), &pat.kind)
         {
             let has_shorthand_field_name = field_patterns.iter().any(|field| field.is_shorthand);
             if has_shorthand_field_name {
@@ -1659,7 +1638,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         fields: &'tcx [hir::PatField<'tcx>],
         variant: &ty::VariantDef,
     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-        if let (CtorKind::Fn, PatKind::Struct(qpath, ..)) = (variant.ctor_kind, &pat.kind) {
+        if let (Some(CtorKind::Fn), PatKind::Struct(qpath, ..)) = (variant.ctor_kind(), &pat.kind) {
             let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
                 s.print_qpath(qpath, false)
             });
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 6c2ee35fa50..58ced6a1d3b 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -361,9 +361,12 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
 
     fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) {
         intravisit::walk_ty(self, hir_ty);
-        let ty = self.fcx.node_ty(hir_ty.hir_id);
-        let ty = self.resolve(ty, &hir_ty.span);
-        self.write_ty_to_typeck_results(hir_ty.hir_id, ty);
+        // If there are type checking errors, Type privacy pass will stop,
+        // so we may not get the type from hid_id, see #104513
+        if let Some(ty) = self.fcx.node_ty_opt(hir_ty.hir_id) {
+            let ty = self.resolve(ty, &hir_ty.span);
+            self.write_ty_to_typeck_results(hir_ty.hir_id, ty);
+        }
     }
 
     fn visit_infer(&mut self, inf: &'tcx hir::InferArg) {
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 25c1b2e1c43..58d6e6d7efd 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -322,7 +322,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) {
 
     let incr_comp_session_dir: PathBuf = sess.incr_comp_session_dir().clone();
 
-    if sess.has_errors_or_delayed_span_bugs() {
+    if let Some(_) = sess.has_errors_or_delayed_span_bugs() {
         // If there have been any errors during compilation, we don't want to
         // publish this session directory. Rather, we'll just delete it.
 
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 71035031497..6e9dcdd981e 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -28,7 +28,7 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) {
             return;
         }
         // This is going to be deleted in finalize_session_directory, so let's not create it
-        if sess.has_errors_or_delayed_span_bugs() {
+        if let Some(_) = sess.has_errors_or_delayed_span_bugs() {
             return;
         }
 
@@ -89,7 +89,7 @@ pub fn save_work_product_index(
         return;
     }
     // This is going to be deleted in finalize_session_directory, so let's not create it
-    if sess.has_errors_or_delayed_span_bugs() {
+    if let Some(_) = sess.has_errors_or_delayed_span_bugs() {
         return;
     }
 
diff --git a/compiler/rustc_index/Cargo.toml b/compiler/rustc_index/Cargo.toml
index d8ea5aa80b8..e1cda5a9edd 100644
--- a/compiler/rustc_index/Cargo.toml
+++ b/compiler/rustc_index/Cargo.toml
@@ -7,6 +7,10 @@ edition = "2021"
 
 [dependencies]
 arrayvec = { version = "0.7", default-features = false }
-rustc_serialize = { path = "../rustc_serialize" }
-rustc_macros = { path = "../rustc_macros" }
+rustc_serialize = { path = "../rustc_serialize", optional = true }
+rustc_macros = { path = "../rustc_macros", optional = true }
 smallvec = "1.8.1"
+
+[features]
+default = ["nightly"]
+nightly = ["rustc_serialize", "rustc_macros"]
diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs
index 23a4c1f0696..db2c7915256 100644
--- a/compiler/rustc_index/src/lib.rs
+++ b/compiler/rustc_index/src/lib.rs
@@ -1,17 +1,25 @@
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
-#![feature(allow_internal_unstable)]
-#![feature(extend_one)]
-#![feature(min_specialization)]
-#![feature(new_uninit)]
-#![feature(step_trait)]
-#![feature(stmt_expr_attributes)]
-#![feature(test)]
+#![cfg_attr(
+    feature = "nightly",
+    feature(
+        allow_internal_unstable,
+        extend_one,
+        min_specialization,
+        new_uninit,
+        step_trait,
+        stmt_expr_attributes,
+        test
+    )
+)]
 
+#[cfg(feature = "nightly")]
 pub mod bit_set;
+#[cfg(feature = "nightly")]
 pub mod interval;
 pub mod vec;
 
+#[cfg(feature = "rustc_macros")]
 pub use rustc_macros::newtype_index;
 
 /// Type size assertion. The first argument is a type and the second argument is its expected size.
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index 4172ce3bb30..39aa27a23c1 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -1,3 +1,4 @@
+#[cfg(feature = "rustc_serialize")]
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 
 use std::fmt;
@@ -17,10 +18,12 @@ pub trait Idx: Copy + 'static + Eq + PartialEq + Debug + Hash {
 
     fn index(self) -> usize;
 
+    #[inline]
     fn increment_by(&mut self, amount: usize) {
         *self = self.plus(amount);
     }
 
+    #[inline]
     fn plus(self, amount: usize) -> Self {
         Self::new(self.index() + amount)
     }
@@ -59,12 +62,14 @@ pub struct IndexVec<I: Idx, T> {
 // not the phantom data.
 unsafe impl<I: Idx, T> Send for IndexVec<I, T> where T: Send {}
 
+#[cfg(feature = "rustc_serialize")]
 impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for IndexVec<I, T> {
     fn encode(&self, s: &mut S) {
         Encodable::encode(&self.raw, s);
     }
 }
 
+#[cfg(feature = "rustc_serialize")]
 impl<D: Decoder, I: Idx, T: Decodable<D>> Decodable<D> for IndexVec<I, T> {
     fn decode(d: &mut D) -> Self {
         IndexVec { raw: Decodable::decode(d), _marker: PhantomData }
@@ -357,11 +362,13 @@ impl<I: Idx, T> Extend<T> for IndexVec<I, T> {
     }
 
     #[inline]
+    #[cfg(feature = "nightly")]
     fn extend_one(&mut self, item: T) {
         self.raw.push(item);
     }
 
     #[inline]
+    #[cfg(feature = "nightly")]
     fn extend_reserve(&mut self, additional: usize) {
         self.raw.reserve(additional);
     }
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 5ff3779fa14..2483ab724a4 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -81,6 +81,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 .normalize_fn_sig_for_diagnostic
                 .as_ref()
                 .map(|f| f.clone()),
+            intercrate: self.intercrate,
         }
     }
 }
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 34f54328230..b4a427a5d41 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -23,11 +23,10 @@ use rustc_index::vec::Idx;
 use rustc_index::vec::IndexVec;
 use rustc_middle::arena::ArenaAllocatable;
 use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
-use rustc_middle::ty::{self, BoundVar, Const, ToPredicate, Ty, TyCtxt};
+use rustc_middle::ty::{self, BoundVar, ToPredicate, Ty, TyCtxt};
 use rustc_span::Span;
 use std::fmt::Debug;
 use std::iter;
@@ -729,10 +728,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
         });
     }
 
-    fn const_equate(&mut self, _a: Const<'tcx>, _b: Const<'tcx>) {
-        span_bug!(self.cause.span(), "generic_const_exprs: unreachable `const_equate`");
-    }
-
     fn normalization() -> NormalizationStrategy {
         NormalizationStrategy::Eager
     }
@@ -741,11 +736,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
         true
     }
 
-    fn register_opaque_type_obligations(
-        &mut self,
-        obligations: PredicateObligations<'tcx>,
-    ) -> Result<(), TypeError<'tcx>> {
+    fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
         self.obligations.extend(obligations);
-        Ok(())
     }
 }
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index c2552561c42..eec938cefbb 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -450,6 +450,15 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
             ty::Binder::dummy(predicate),
         ));
     }
+
+    pub fn mark_ambiguous(&mut self) {
+        self.obligations.push(Obligation::new(
+            self.tcx(),
+            self.trace.cause.clone(),
+            self.param_env,
+            ty::Binder::dummy(ty::PredicateKind::Ambiguous),
+        ));
+    }
 }
 
 struct Generalizer<'cx, 'tcx> {
@@ -521,6 +530,11 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
+
+    fn intercrate(&self) -> bool {
+        self.infcx.intercrate
+    }
+
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.param_env
     }
@@ -533,6 +547,10 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
         true
     }
 
+    fn mark_ambiguous(&mut self) {
+        span_bug!(self.cause.span, "opaque types are handled in `tys`");
+    }
+
     fn binders<T>(
         &mut self,
         a: ty::Binder<'tcx, T>,
@@ -657,6 +675,10 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                 // relatable.
                 Ok(t)
             }
+            ty::Opaque(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),
         }?;
 
@@ -799,6 +821,11 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
         self.infcx.tcx
     }
 
+    fn intercrate(&self) -> bool {
+        assert!(!self.infcx.intercrate);
+        false
+    }
+
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.param_env
     }
@@ -811,6 +838,10 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
         true
     }
 
+    fn mark_ambiguous(&mut self) {
+        bug!()
+    }
+
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _variance: ty::Variance,
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index 59728148a84..8682f4d3b7a 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -32,6 +32,10 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
         self.fields.tcx()
     }
 
+    fn intercrate(&self) -> bool {
+        self.fields.infcx.intercrate
+    }
+
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.fields.param_env
     }
@@ -40,6 +44,10 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
         self.a_is_expected
     }
 
+    fn mark_ambiguous(&mut self) {
+        self.fields.mark_ambiguous();
+    }
+
     fn relate_item_substs(
         &mut self,
         _item_def_id: DefId,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index b8aff69b371..0dee3be7054 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -65,7 +65,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg};
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan};
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
+use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
@@ -1967,7 +1967,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     .variants()
                     .iter()
                     .filter(|variant| {
-                        variant.fields.len() == 1 && variant.ctor_kind == hir::def::CtorKind::Fn
+                        variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
                     })
                     .filter_map(|variant| {
                         let sole_field = &variant.fields[0];
@@ -2937,6 +2937,11 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
         self.0.tcx
     }
 
+    fn intercrate(&self) -> bool {
+        assert!(!self.0.intercrate);
+        false
+    }
+
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         // Unused, only for consts which we treat as always equal
         ty::ParamEnv::empty()
@@ -2950,6 +2955,10 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
         true
     }
 
+    fn mark_ambiguous(&mut self) {
+        bug!()
+    }
+
     fn relate_with_variance<T: relate::Relate<'tcx>>(
         &mut self,
         _variance: ty::Variance,
diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs
index 6ffefcb7a28..7f27b35a54e 100644
--- a/compiler/rustc_infer/src/infer/glb.rs
+++ b/compiler/rustc_infer/src/infer/glb.rs
@@ -30,6 +30,11 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
         "Glb"
     }
 
+    fn intercrate(&self) -> bool {
+        assert!(!self.fields.infcx.intercrate);
+        false
+    }
+
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.fields.tcx()
     }
@@ -42,6 +47,10 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
         self.a_is_expected
     }
 
+    fn mark_ambiguous(&mut self) {
+        bug!("mark_ambiguous used outside of coherence");
+    }
+
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs
index d6e56fcb7fd..97ed4729bd0 100644
--- a/compiler/rustc_infer/src/infer/lub.rs
+++ b/compiler/rustc_infer/src/infer/lub.rs
@@ -30,6 +30,11 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
         "Lub"
     }
 
+    fn intercrate(&self) -> bool {
+        assert!(!self.fields.infcx.intercrate);
+        false
+    }
+
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.fields.tcx()
     }
@@ -42,6 +47,10 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
         self.a_is_expected
     }
 
+    fn mark_ambiguous(&mut self) {
+        bug!("mark_ambiguous used outside of coherence");
+    }
+
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index b9ed6b28c22..2798477d181 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -337,6 +337,26 @@ pub struct InferCtxt<'tcx> {
 
     normalize_fn_sig_for_diagnostic:
         Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
+
+    /// During coherence we have to assume that other crates may add
+    /// additional impls which we currently don't know about.
+    ///
+    /// To deal with this evaluation should be conservative
+    /// and consider the possibility of impls from outside this crate.
+    /// This comes up primarily when resolving ambiguity. Imagine
+    /// there is some trait reference `$0: Bar` where `$0` is an
+    /// inference variable. If `intercrate` is true, then we can never
+    /// say for sure that this reference is not implemented, even if
+    /// there are *no impls at all for `Bar`*, because `$0` could be
+    /// bound to some type that in a downstream crate that implements
+    /// `Bar`.
+    ///
+    /// Outside of coherence we set this to false because we are only
+    /// interested in types that the user could actually have written.
+    /// In other words, we consider `$0: Bar` to be unimplemented if
+    /// there is no type that the user could *actually name* that
+    /// would satisfy it. This avoids crippling inference, basically.
+    pub intercrate: bool,
 }
 
 /// See the `error_reporting` module for more details.
@@ -552,6 +572,8 @@ pub struct InferCtxtBuilder<'tcx> {
     tcx: TyCtxt<'tcx>,
     defining_use_anchor: DefiningAnchor,
     considering_regions: bool,
+    /// Whether we are in coherence mode.
+    intercrate: bool,
     normalize_fn_sig_for_diagnostic:
         Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
 }
@@ -567,6 +589,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
             defining_use_anchor: DefiningAnchor::Error,
             considering_regions: true,
             normalize_fn_sig_for_diagnostic: None,
+            intercrate: false,
         }
     }
 }
@@ -583,6 +606,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
         self
     }
 
+    pub fn intercrate(mut self) -> Self {
+        self.intercrate = true;
+        self
+    }
+
     pub fn ignoring_regions(mut self) -> Self {
         self.considering_regions = false;
         self
@@ -622,6 +650,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
             defining_use_anchor,
             considering_regions,
             ref normalize_fn_sig_for_diagnostic,
+            intercrate,
         } = *self;
         InferCtxt {
             tcx,
@@ -641,6 +670,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
             normalize_fn_sig_for_diagnostic: normalize_fn_sig_for_diagnostic
                 .as_ref()
                 .map(|f| f.clone()),
+            intercrate,
         }
     }
 }
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 167a82d4499..4f8460955c3 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -25,7 +25,7 @@ use crate::infer::combine::ConstEquateRelation;
 use crate::infer::InferCtxt;
 use crate::infer::{ConstVarValue, ConstVariableValue};
 use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::traits::PredicateObligation;
+use crate::traits::{Obligation, PredicateObligation};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::TypeError;
@@ -92,11 +92,7 @@ pub trait TypeRelatingDelegate<'tcx> {
         info: ty::VarianceDiagInfo<'tcx>,
     );
 
-    fn const_equate(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>);
-    fn register_opaque_type_obligations(
-        &mut self,
-        obligations: Vec<PredicateObligation<'tcx>>,
-    ) -> Result<(), TypeError<'tcx>>;
+    fn register_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>);
 
     /// Creates a new universe index. Used when instantiating placeholders.
     fn create_next_universe(&mut self) -> ty::UniverseIndex;
@@ -419,7 +415,7 @@ where
             .infcx
             .handle_opaque_type(a, b, true, &cause, self.delegate.param_env())?
             .obligations;
-        self.delegate.register_opaque_type_obligations(obligations)?;
+        self.delegate.register_obligations(obligations);
         trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
         Ok(a)
     }
@@ -531,6 +527,10 @@ where
         self.infcx.tcx
     }
 
+    fn intercrate(&self) -> bool {
+        self.infcx.intercrate
+    }
+
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.delegate.param_env()
     }
@@ -543,6 +543,17 @@ where
         true
     }
 
+    fn mark_ambiguous(&mut self) {
+        let cause = ObligationCause::dummy_with_span(self.delegate.span());
+        let param_env = self.delegate.param_env();
+        self.delegate.register_obligations(vec![Obligation::new(
+            self.tcx(),
+            cause,
+            param_env,
+            ty::Binder::dummy(ty::PredicateKind::Ambiguous),
+        )]);
+    }
+
     #[instrument(skip(self, info), level = "trace", ret)]
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
@@ -800,8 +811,12 @@ impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D>
 where
     D: TypeRelatingDelegate<'tcx>,
 {
-    fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
-        self.delegate.const_equate(a, b);
+    fn const_equate_obligation(&mut self, _a: ty::Const<'tcx>, _b: ty::Const<'tcx>) {
+        // We don't have to worry about the equality of consts during borrow checking
+        // as consts always have a static lifetime.
+        // FIXME(oli-obk): is this really true? We can at least have HKL and with
+        // inline consts we may have further lifetimes that may be unsound to treat as
+        // 'static.
     }
 }
 
@@ -898,6 +913,11 @@ where
         self.infcx.tcx
     }
 
+    fn intercrate(&self) -> bool {
+        assert!(!self.infcx.intercrate);
+        false
+    }
+
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.delegate.param_env()
     }
@@ -910,6 +930,10 @@ where
         true
     }
 
+    fn mark_ambiguous(&mut self) {
+        bug!()
+    }
+
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index 2d19d1823fd..8f780579451 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -29,6 +29,7 @@ pub fn explicit_outlives_bounds<'tcx>(
             | ty::PredicateKind::TypeOutlives(..)
             | ty::PredicateKind::ConstEvaluatable(..)
             | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::Ambiguous
             | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
             ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
                 Some(OutlivesBound::RegionSubRegion(r_b, r_a))
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 a5c21f0fb9b..5d204dd70ed 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -136,6 +136,11 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
     fn tag(&self) -> &'static str {
         "Match"
     }
+
+    fn intercrate(&self) -> bool {
+        false
+    }
+
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
@@ -146,6 +151,10 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
         true
     } // irrelevant
 
+    fn mark_ambiguous(&mut self) {
+        bug!()
+    }
+
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _: ty::Variance,
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index bd3c5780b89..2c6987cc3f4 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -35,6 +35,11 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
     fn tag(&self) -> &'static str {
         "Sub"
     }
+
+    fn intercrate(&self) -> bool {
+        self.fields.infcx.intercrate
+    }
+
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.fields.infcx.tcx
     }
@@ -47,6 +52,10 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
         self.a_is_expected
     }
 
+    fn mark_ambiguous(&mut self) {
+        self.fields.mark_ambiguous()
+    }
+
     fn with_cause<F, R>(&mut self, cause: Cause, f: F) -> R
     where
         F: FnOnce(&mut Self) -> R,
diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs
index 54224c9b5de..d3519f4b37b 100644
--- a/compiler/rustc_infer/src/traits/engine.rs
+++ b/compiler/rustc_infer/src/traits/engine.rs
@@ -8,14 +8,6 @@ use super::FulfillmentError;
 use super::{ObligationCause, PredicateObligation};
 
 pub trait TraitEngine<'tcx>: 'tcx {
-    fn normalize_projection_type(
-        &mut self,
-        infcx: &InferCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        projection_ty: ty::ProjectionTy<'tcx>,
-        cause: ObligationCause<'tcx>,
-    ) -> Ty<'tcx>;
-
     /// Requires that `ty` must implement the trait with `def_id` in
     /// the given environment. This trait must not have any type
     /// parameters (except for `Self`).
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index e12c069dcc1..b2a31ac7e6f 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -285,6 +285,7 @@ impl<'tcx> Elaborator<'tcx> {
             ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                 // Nothing to elaborate
             }
+            ty::PredicateKind::Ambiguous => {}
         }
     }
 }
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 89aaa0b95e4..99c934862c4 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -304,7 +304,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
                 parse_sess_created(&mut sess.parse_sess);
             }
 
-            let temps_dir = sess.opts.unstable_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o));
+            let temps_dir = sess.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
 
             let compiler = Compiler {
                 sess: Lrc::new(sess),
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 91d180e1eb7..fc0b11183f7 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -33,11 +33,7 @@ pub struct Query<T> {
 
 impl<T> Query<T> {
     fn compute<F: FnOnce() -> Result<T>>(&self, f: F) -> Result<&Query<T>> {
-        let mut result = self.result.borrow_mut();
-        if result.is_none() {
-            *result = Some(f());
-        }
-        result.as_ref().unwrap().as_ref().map(|_| self).map_err(|err| *err)
+        self.result.borrow_mut().get_or_insert_with(f).as_ref().map(|_| self).map_err(|&err| err)
     }
 
     /// Takes ownership of the query result. Further attempts to take or peek the query
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 2fe3fb2fa56..4142964a0da 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -68,10 +68,7 @@ pub fn create_session(
     let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend {
         make_codegen_backend(&sopts)
     } else {
-        get_codegen_backend(
-            &sopts.maybe_sysroot,
-            sopts.unstable_opts.codegen_backend.as_ref().map(|name| &name[..]),
-        )
+        get_codegen_backend(&sopts.maybe_sysroot, sopts.unstable_opts.codegen_backend.as_deref())
     };
 
     // target_override is documented to be called before init(), so this is okay
@@ -260,7 +257,7 @@ pub fn rustc_path<'a>() -> Option<&'a Path> {
 
     const BIN_PATH: &str = env!("RUSTC_INSTALL_BINDIR");
 
-    RUSTC_PATH.get_or_init(|| get_rustc_path_inner(BIN_PATH)).as_ref().map(|v| &**v)
+    RUSTC_PATH.get_or_init(|| get_rustc_path_inner(BIN_PATH)).as_deref()
 }
 
 fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> {
diff --git a/compiler/rustc_lexer/src/unescape/tests.rs b/compiler/rustc_lexer/src/unescape/tests.rs
index c7ca8fd16ae..1c25b03fdb2 100644
--- a/compiler/rustc_lexer/src/unescape/tests.rs
+++ b/compiler/rustc_lexer/src/unescape/tests.rs
@@ -132,8 +132,7 @@ fn test_unescape_str_good() {
                 }
             }
         });
-        let buf = buf.as_ref().map(|it| it.as_ref());
-        assert_eq!(buf, Ok(expected))
+        assert_eq!(buf.as_deref(), Ok(expected))
     }
 
     check("foo", "foo");
@@ -250,8 +249,7 @@ fn test_unescape_byte_str_good() {
                 }
             }
         });
-        let buf = buf.as_ref().map(|it| it.as_ref());
-        assert_eq!(buf, Ok(expected))
+        assert_eq!(buf.as_deref(), Ok(expected))
     }
 
     check("foo", b"foo");
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 8c779579a4f..ada3c3b67fb 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1659,6 +1659,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
                     Coerce(..) |
                     ConstEvaluatable(..) |
                     ConstEquate(..) |
+                    Ambiguous |
                     TypeWellFormedFromEnv(..) => continue,
                 };
                 if predicate.is_global() {
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 589b4d6a10f..67cf66f4708 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -1245,6 +1245,23 @@ impl<'tcx> LateContext<'tcx> {
 
         AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]).unwrap()
     }
+
+    /// Returns the associated type `name` for `self_ty` as an implementation of `trait_id`.
+    /// Do not invoke without first verifying that the type implements the trait.
+    pub fn get_associated_type(
+        &self,
+        self_ty: Ty<'tcx>,
+        trait_id: DefId,
+        name: &str,
+    ) -> Option<Ty<'tcx>> {
+        let tcx = self.tcx;
+        tcx.associated_items(trait_id)
+            .find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id)
+            .and_then(|assoc| {
+                let proj = tcx.mk_projection(assoc.def_id, tcx.mk_substs_trait(self_ty, []));
+                tcx.try_normalize_erasing_regions(self.param_env, proj).ok()
+            })
+    }
 }
 
 impl<'tcx> abi::HasDataLayout for LateContext<'tcx> {
diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
new file mode 100644
index 00000000000..1d29a234a3c
--- /dev/null
+++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
@@ -0,0 +1,92 @@
+use crate::{LateContext, LateLintPass, LintContext};
+
+use rustc_errors::DelayDm;
+use rustc_hir as hir;
+use rustc_middle::{traits::util::supertraits, ty};
+use rustc_span::sym;
+
+declare_lint! {
+    /// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
+    /// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
+    ///
+    /// These implementations will become shadowed when the `trait_upcasting` feature is stabilized.
+    /// The `deref` functions will no longer be called implicitly, so there might be behavior change.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![deny(deref_into_dyn_supertrait)]
+    /// #![allow(dead_code)]
+    ///
+    /// use core::ops::Deref;
+    ///
+    /// trait A {}
+    /// trait B: A {}
+    /// impl<'a> Deref for dyn 'a + B {
+    ///     type Target = dyn A;
+    ///     fn deref(&self) -> &Self::Target {
+    ///         todo!()
+    ///     }
+    /// }
+    ///
+    /// fn take_a(_: &dyn A) { }
+    ///
+    /// fn take_b(b: &dyn B) {
+    ///     take_a(b);
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// The dyn upcasting coercion feature adds new coercion rules, taking priority
+    /// over certain other coercion rules, which will cause some behavior change.
+    pub DEREF_INTO_DYN_SUPERTRAIT,
+    Warn,
+    "`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
+    };
+}
+
+declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]);
+
+impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
+        // `Deref` is being implemented for `t`
+        if let hir::ItemKind::Impl(impl_) = item.kind
+            && let Some(trait_) = &impl_.of_trait
+            && let t = cx.tcx.type_of(item.owner_id)
+            && let opt_did @ Some(did) = trait_.trait_def_id()
+            && opt_did == cx.tcx.lang_items().deref_trait()
+            // `t` is `dyn t_principal`
+            && let ty::Dynamic(data, _, ty::Dyn) = t.kind()
+            && let Some(t_principal) = data.principal()
+            // `<T as Deref>::Target` is `dyn target_principal`
+            && let Some(target) = cx.get_associated_type(t, did, "Target")
+            && let ty::Dynamic(data, _, ty::Dyn) = target.kind()
+            && let Some(target_principal) = data.principal()
+            // `target_principal` is a supertrait of `t_principal`
+            && supertraits(cx.tcx, t_principal.with_self_ty(cx.tcx, cx.tcx.types.trait_object_dummy_self))
+                .any(|sup| sup.map_bound(|x| ty::ExistentialTraitRef::erase_self_ty(cx.tcx, x)) == target_principal)
+        {
+            cx.struct_span_lint(
+                DEREF_INTO_DYN_SUPERTRAIT,
+                cx.tcx.def_span(item.owner_id.def_id),
+                DelayDm(|| {
+                    format!(
+                        "`{t}` implements `Deref` with supertrait `{target_principal}` as target"
+                    )
+                }),
+                |lint| {
+                    if let Some(target_span) = impl_.items.iter().find_map(|i| (i.ident.name == sym::Target).then_some(i.span)) {
+                        lint.span_label(target_span, "target type is set here");
+                    }
+
+                    lint
+                },
+            )
+        }
+    }
+}
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index fc760ee3b8f..a7a4d0ca527 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -159,8 +159,8 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
     }
 
     fn visit_variant_data(&mut self, s: &'a ast::VariantData) {
-        if let Some(ctor_hir_id) = s.ctor_id() {
-            self.check_id(ctor_hir_id);
+        if let Some(ctor_node_id) = s.ctor_node_id() {
+            self.check_id(ctor_node_id);
         }
         ast_visit::walk_struct_def(self, s);
     }
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index ebb7de70e05..b6027476adf 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -49,6 +49,7 @@ extern crate tracing;
 mod array_into_iter;
 pub mod builtin;
 mod context;
+mod deref_into_dyn_supertrait;
 mod early;
 mod enum_intrinsics_non_enums;
 mod errors;
@@ -87,6 +88,7 @@ use rustc_span::Span;
 
 use array_into_iter::ArrayIntoIter;
 use builtin::*;
+use deref_into_dyn_supertrait::*;
 use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
 use for_loops_over_fallibles::*;
 use hidden_unicode_codepoints::*;
@@ -192,6 +194,7 @@ macro_rules! late_lint_mod_passes {
             $args,
             [
                 ForLoopsOverFallibles: ForLoopsOverFallibles,
+                DerefIntoDynSupertrait: DerefIntoDynSupertrait,
                 HardwiredLints: HardwiredLints,
                 ImproperCTypesDeclarations: ImproperCTypesDeclarations,
                 ImproperCTypesDefinitions: ImproperCTypesDefinitions,
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index afc568f3a50..297b509d402 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -12,7 +12,7 @@ use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable,
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
-use rustc_target::abi::{Abi, WrappingRange};
+use rustc_target::abi::{Abi, Size, WrappingRange};
 use rustc_target::abi::{Integer, TagEncoding, Variants};
 use rustc_target::spec::abi::Abi as SpecAbi;
 
@@ -225,11 +225,11 @@ fn report_bin_hex_error(
     cx: &LateContext<'_>,
     expr: &hir::Expr<'_>,
     ty: attr::IntType,
+    size: Size,
     repr_str: String,
     val: u128,
     negative: bool,
 ) {
-    let size = Integer::from_attr(&cx.tcx, ty).size();
     cx.struct_span_lint(
         OVERFLOWING_LITERALS,
         expr.span,
@@ -352,6 +352,7 @@ fn lint_int_literal<'tcx>(
                 cx,
                 e,
                 attr::IntType::SignedInt(ty::ast_int_ty(t)),
+                Integer::from_int_ty(cx, t).size(),
                 repr_str,
                 v,
                 negative,
@@ -437,6 +438,7 @@ fn lint_uint_literal<'tcx>(
                 cx,
                 e,
                 attr::IntType::UnsignedInt(ty::ast_uint_ty(t)),
+                Integer::from_uint_ty(cx, t).size(),
                 repr_str,
                 lit_val,
                 false,
@@ -1376,7 +1378,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
             let (largest, slargest, largest_index) = iter::zip(enum_definition.variants, variants)
                 .map(|(variant, variant_layout)| {
                     // Subtract the size of the enum tag.
-                    let bytes = variant_layout.size().bytes().saturating_sub(tag_size);
+                    let bytes = variant_layout.size.bytes().saturating_sub(tag_size);
 
                     debug!("- variant `{}` is {} bytes large", variant.ident, bytes);
                     bytes
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 100a8788763..5c9217db118 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -13,6 +13,7 @@ use rustc_middle::ty::{self, DefIdTree, Ty};
 use rustc_span::symbol::Symbol;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{BytePos, Span};
+use std::iter;
 
 declare_lint! {
     /// The `unused_must_use` lint detects unused result of a type flagged as
@@ -113,30 +114,19 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
         }
 
         let ty = cx.typeck_results().expr_ty(&expr);
-        let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, expr.span, "", "", 1);
 
-        let mut fn_warned = false;
-        let mut op_warned = false;
-        let maybe_def_id = match expr.kind {
-            hir::ExprKind::Call(ref callee, _) => {
-                match callee.kind {
-                    hir::ExprKind::Path(ref qpath) => {
-                        match cx.qpath_res(qpath, callee.hir_id) {
-                            Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => Some(def_id),
-                            // `Res::Local` if it was a closure, for which we
-                            // do not currently support must-use linting
-                            _ => None,
-                        }
-                    }
-                    _ => None,
-                }
+        let must_use_result = is_ty_must_use(cx, ty, &expr, expr.span);
+        let type_lint_emitted_or_suppressed = match must_use_result {
+            Some(path) => {
+                emit_must_use_untranslated(cx, &path, "", "", 1);
+                true
             }
-            hir::ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
-            _ => None,
+            None => false,
         };
-        if let Some(def_id) = maybe_def_id {
-            fn_warned = check_must_use_def(cx, def_id, expr.span, "return value of ", "");
-        } else if type_permits_lack_of_use {
+
+        let fn_warned = check_fn_must_use(cx, expr);
+
+        if !fn_warned && type_lint_emitted_or_suppressed {
             // We don't warn about unused unit or uninhabited types.
             // (See https://github.com/rust-lang/rust/issues/43806 for details.)
             return;
@@ -170,6 +160,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
             _ => None,
         };
 
+        let mut op_warned = false;
+
         if let Some(must_use_op) = must_use_op {
             cx.struct_span_lint(UNUSED_MUST_USE, expr.span, fluent::lint_unused_op, |lint| {
                 lint.set_arg("op", must_use_op)
@@ -184,22 +176,64 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
             op_warned = true;
         }
 
-        if !(type_permits_lack_of_use || fn_warned || op_warned) {
+        if !(type_lint_emitted_or_suppressed || fn_warned || op_warned) {
             cx.struct_span_lint(UNUSED_RESULTS, s.span, fluent::lint_unused_result, |lint| {
                 lint.set_arg("ty", ty)
             });
         }
 
-        // Returns whether an error has been emitted (and thus another does not need to be later).
-        fn check_must_use_ty<'tcx>(
+        fn check_fn_must_use(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+            let maybe_def_id = match expr.kind {
+                hir::ExprKind::Call(ref callee, _) => {
+                    match callee.kind {
+                        hir::ExprKind::Path(ref qpath) => {
+                            match cx.qpath_res(qpath, callee.hir_id) {
+                                Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => Some(def_id),
+                                // `Res::Local` if it was a closure, for which we
+                                // do not currently support must-use linting
+                                _ => None,
+                            }
+                        }
+                        _ => None,
+                    }
+                }
+                hir::ExprKind::MethodCall(..) => {
+                    cx.typeck_results().type_dependent_def_id(expr.hir_id)
+                }
+                _ => None,
+            };
+            if let Some(def_id) = maybe_def_id {
+                check_must_use_def(cx, def_id, expr.span, "return value of ", "")
+            } else {
+                false
+            }
+        }
+
+        /// A path through a type to a must_use source. Contains useful info for the lint.
+        #[derive(Debug)]
+        enum MustUsePath {
+            /// Suppress must_use checking.
+            Suppressed,
+            /// The root of the normal must_use lint with an optional message.
+            Def(Span, DefId, Option<Symbol>),
+            Boxed(Box<Self>),
+            Opaque(Box<Self>),
+            TraitObject(Box<Self>),
+            TupleElement(Vec<(usize, Self)>),
+            Array(Box<Self>, u64),
+            /// The root of the unused_closures lint.
+            Closure(Span),
+            /// The root of the unused_generators lint.
+            Generator(Span),
+        }
+
+        #[instrument(skip(cx, expr), level = "debug", ret)]
+        fn is_ty_must_use<'tcx>(
             cx: &LateContext<'tcx>,
             ty: Ty<'tcx>,
             expr: &hir::Expr<'_>,
             span: Span,
-            descr_pre: &str,
-            descr_post: &str,
-            plural_len: usize,
-        ) -> bool {
+        ) -> Option<MustUsePath> {
             if ty.is_unit()
                 || !ty.is_inhabited_from(
                     cx.tcx,
@@ -207,87 +241,177 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                     cx.param_env,
                 )
             {
-                return true;
+                return Some(MustUsePath::Suppressed);
             }
 
-            let plural_suffix = pluralize!(plural_len);
-
             match *ty.kind() {
                 ty::Adt(..) if ty.is_box() => {
                     let boxed_ty = ty.boxed_ty();
-                    let descr_pre = &format!("{}boxed ", descr_pre);
-                    check_must_use_ty(cx, boxed_ty, expr, span, descr_pre, descr_post, plural_len)
+                    is_ty_must_use(cx, boxed_ty, expr, span)
+                        .map(|inner| MustUsePath::Boxed(Box::new(inner)))
                 }
-                ty::Adt(def, _) => check_must_use_def(cx, def.did(), span, descr_pre, descr_post),
+                ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
                 ty::Opaque(def, _) => {
-                    let mut has_emitted = false;
-                    for obligation in elaborate_predicates_with_span(
+                    elaborate_predicates_with_span(
                         cx.tcx,
                         cx.tcx.explicit_item_bounds(def).iter().cloned(),
-                    ) {
+                    )
+                    .filter_map(|obligation| {
                         // We only look at the `DefId`, so it is safe to skip the binder here.
                         if let ty::PredicateKind::Trait(ref poly_trait_predicate) =
                             obligation.predicate.kind().skip_binder()
                         {
                             let def_id = poly_trait_predicate.trait_ref.def_id;
-                            let descr_pre =
-                                &format!("{}implementer{} of ", descr_pre, plural_suffix,);
-                            if check_must_use_def(cx, def_id, span, descr_pre, descr_post) {
-                                has_emitted = true;
-                                break;
-                            }
+
+                            is_def_must_use(cx, def_id, span)
+                        } else {
+                            None
                         }
-                    }
-                    has_emitted
+                    })
+                    .map(|inner| MustUsePath::Opaque(Box::new(inner)))
+                    .next()
                 }
-                ty::Dynamic(binder, _, _) => {
-                    let mut has_emitted = false;
-                    for predicate in binder.iter() {
+                ty::Dynamic(binders, _, _) => binders
+                    .iter()
+                    .filter_map(|predicate| {
                         if let ty::ExistentialPredicate::Trait(ref trait_ref) =
                             predicate.skip_binder()
                         {
                             let def_id = trait_ref.def_id;
-                            let descr_post =
-                                &format!(" trait object{}{}", plural_suffix, descr_post,);
-                            if check_must_use_def(cx, def_id, span, descr_pre, descr_post) {
-                                has_emitted = true;
-                                break;
-                            }
+                            is_def_must_use(cx, def_id, span)
+                        } else {
+                            None
                         }
-                    }
-                    has_emitted
-                }
-                ty::Tuple(ref tys) => {
-                    let mut has_emitted = false;
-                    let comps = if let hir::ExprKind::Tup(comps) = expr.kind {
-                        debug_assert_eq!(comps.len(), tys.len());
-                        comps
+                        .map(|inner| MustUsePath::TraitObject(Box::new(inner)))
+                    })
+                    .next(),
+                ty::Tuple(tys) => {
+                    let elem_exprs = if let hir::ExprKind::Tup(elem_exprs) = expr.kind {
+                        debug_assert_eq!(elem_exprs.len(), tys.len());
+                        elem_exprs
                     } else {
                         &[]
                     };
-                    for (i, ty) in tys.iter().enumerate() {
-                        let descr_post = &format!(" in tuple element {}", i);
-                        let e = comps.get(i).unwrap_or(expr);
-                        let span = e.span;
-                        if check_must_use_ty(cx, ty, e, span, descr_pre, descr_post, plural_len) {
-                            has_emitted = true;
-                        }
+
+                    // Default to `expr`.
+                    let elem_exprs = elem_exprs.iter().chain(iter::repeat(expr));
+
+                    let nested_must_use = tys
+                        .iter()
+                        .zip(elem_exprs)
+                        .enumerate()
+                        .filter_map(|(i, (ty, expr))| {
+                            is_ty_must_use(cx, ty, expr, expr.span).map(|path| (i, path))
+                        })
+                        .collect::<Vec<_>>();
+
+                    if !nested_must_use.is_empty() {
+                        Some(MustUsePath::TupleElement(nested_must_use))
+                    } else {
+                        None
                     }
-                    has_emitted
                 }
                 ty::Array(ty, len) => match len.try_eval_usize(cx.tcx, cx.param_env) {
                     // If the array is empty we don't lint, to avoid false positives
-                    Some(0) | None => false,
+                    Some(0) | None => None,
                     // If the array is definitely non-empty, we can do `#[must_use]` checking.
-                    Some(n) => {
-                        let descr_pre = &format!("{}array{} of ", descr_pre, plural_suffix,);
-                        check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, n as usize + 1)
-                    }
+                    Some(len) => is_ty_must_use(cx, ty, expr, span)
+                        .map(|inner| MustUsePath::Array(Box::new(inner), len)),
                 },
-                ty::Closure(..) => {
+                ty::Closure(..) => Some(MustUsePath::Closure(span)),
+                ty::Generator(def_id, ..) => {
+                    // async fn should be treated as "implementor of `Future`"
+                    let must_use = if matches!(
+                        cx.tcx.generator_kind(def_id),
+                        Some(hir::GeneratorKind::Async(..))
+                    ) {
+                        let def_id = cx.tcx.lang_items().future_trait().unwrap();
+                        is_def_must_use(cx, def_id, span)
+                            .map(|inner| MustUsePath::Opaque(Box::new(inner)))
+                    } else {
+                        None
+                    };
+                    must_use.or(Some(MustUsePath::Generator(span)))
+                }
+                _ => None,
+            }
+        }
+
+        fn is_def_must_use(cx: &LateContext<'_>, def_id: DefId, span: Span) -> Option<MustUsePath> {
+            if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) {
+                // check for #[must_use = "..."]
+                let reason = attr.value_str();
+                Some(MustUsePath::Def(span, def_id, reason))
+            } else {
+                None
+            }
+        }
+
+        // Returns whether further errors should be suppressed because either a lint has been emitted or the type should be ignored.
+        fn check_must_use_def(
+            cx: &LateContext<'_>,
+            def_id: DefId,
+            span: Span,
+            descr_pre_path: &str,
+            descr_post_path: &str,
+        ) -> bool {
+            is_def_must_use(cx, def_id, span)
+                .map(|must_use_path| {
+                    emit_must_use_untranslated(
+                        cx,
+                        &must_use_path,
+                        descr_pre_path,
+                        descr_post_path,
+                        1,
+                    )
+                })
+                .is_some()
+        }
+
+        #[instrument(skip(cx), level = "debug")]
+        fn emit_must_use_untranslated(
+            cx: &LateContext<'_>,
+            path: &MustUsePath,
+            descr_pre: &str,
+            descr_post: &str,
+            plural_len: usize,
+        ) {
+            let plural_suffix = pluralize!(plural_len);
+
+            match path {
+                MustUsePath::Suppressed => {}
+                MustUsePath::Boxed(path) => {
+                    let descr_pre = &format!("{}boxed ", descr_pre);
+                    emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
+                }
+                MustUsePath::Opaque(path) => {
+                    let descr_pre = &format!("{}implementer{} of ", descr_pre, plural_suffix);
+                    emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
+                }
+                MustUsePath::TraitObject(path) => {
+                    let descr_post = &format!(" trait object{}{}", plural_suffix, descr_post);
+                    emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
+                }
+                MustUsePath::TupleElement(elems) => {
+                    for (index, path) in elems {
+                        let descr_post = &format!(" in tuple element {}", index);
+                        emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
+                    }
+                }
+                MustUsePath::Array(path, len) => {
+                    let descr_pre = &format!("{}array{} of ", descr_pre, plural_suffix);
+                    emit_must_use_untranslated(
+                        cx,
+                        path,
+                        descr_pre,
+                        descr_post,
+                        plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)),
+                    );
+                }
+                MustUsePath::Closure(span) => {
                     cx.struct_span_lint(
                         UNUSED_MUST_USE,
-                        span,
+                        *span,
                         fluent::lint_unused_closure,
                         |lint| {
                             // FIXME(davidtwco): this isn't properly translatable because of the
@@ -298,12 +422,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                                 .note(fluent::note)
                         },
                     );
-                    true
                 }
-                ty::Generator(..) => {
+                MustUsePath::Generator(span) => {
                     cx.struct_span_lint(
                         UNUSED_MUST_USE,
-                        span,
+                        *span,
                         fluent::lint_unused_generator,
                         |lint| {
                             // FIXME(davidtwco): this isn't properly translatable because of the
@@ -314,40 +437,20 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                                 .note(fluent::note)
                         },
                     );
-                    true
                 }
-                _ => false,
-            }
-        }
-
-        // Returns whether an error has been emitted (and thus another does not need to be later).
-        // FIXME: Args desc_{pre,post}_path could be made lazy by taking Fn() -> &str, but this
-        // would make calling it a big awkward. Could also take String (so args are moved), but
-        // this would still require a copy into the format string, which would only be executed
-        // when needed.
-        fn check_must_use_def(
-            cx: &LateContext<'_>,
-            def_id: DefId,
-            span: Span,
-            descr_pre_path: &str,
-            descr_post_path: &str,
-        ) -> bool {
-            if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) {
-                cx.struct_span_lint(UNUSED_MUST_USE, span, fluent::lint_unused_def, |lint| {
-                    // FIXME(davidtwco): this isn't properly translatable because of the pre/post
-                    // strings
-                    lint.set_arg("pre", descr_pre_path);
-                    lint.set_arg("post", descr_post_path);
-                    lint.set_arg("def", cx.tcx.def_path_str(def_id));
-                    // check for #[must_use = "..."]
-                    if let Some(note) = attr.value_str() {
-                        lint.note(note.as_str());
-                    }
-                    lint
-                });
-                true
-            } else {
-                false
+                MustUsePath::Def(span, def_id, reason) => {
+                    cx.struct_span_lint(UNUSED_MUST_USE, *span, fluent::lint_unused_def, |lint| {
+                        // FIXME(davidtwco): this isn't properly translatable because of the pre/post
+                        // strings
+                        lint.set_arg("pre", descr_pre);
+                        lint.set_arg("post", descr_post);
+                        lint.set_arg("def", cx.tcx.def_path_str(*def_id));
+                        if let Some(note) = reason {
+                            lint.note(note.as_str());
+                        }
+                        lint
+                    });
+                }
             }
         }
     }
@@ -912,6 +1015,7 @@ impl EarlyLintPass for UnusedParens {
         if let ast::TyKind::Paren(r) = &ty.kind {
             match &r.kind {
                 ast::TyKind::TraitObject(..) => {}
+                ast::TyKind::BareFn(b) if b.generic_params.len() > 0 => {}
                 ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {}
                 ast::TyKind::Array(_, len) => {
                     self.check_unused_delims_expr(
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index b80facb1759..df0e17dea3c 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3262,7 +3262,6 @@ declare_lint_pass! {
         UNUSED_TUPLE_STRUCT_FIELDS,
         NON_EXHAUSTIVE_OMITTED_PATTERNS,
         TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
-        DEREF_INTO_DYN_SUPERTRAIT,
         DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
         DUPLICATE_MACRO_ATTRIBUTES,
         SUSPICIOUS_AUTO_TRAIT_IMPLS,
@@ -3765,51 +3764,6 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
-    /// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
-    ///
-    /// These implementations will become shadowed when the `trait_upcasting` feature is stabilized.
-    /// The `deref` functions will no longer be called implicitly, so there might be behavior change.
-    ///
-    /// ### Example
-    ///
-    /// ```rust,compile_fail
-    /// #![deny(deref_into_dyn_supertrait)]
-    /// #![allow(dead_code)]
-    ///
-    /// use core::ops::Deref;
-    ///
-    /// trait A {}
-    /// trait B: A {}
-    /// impl<'a> Deref for dyn 'a + B {
-    ///     type Target = dyn A;
-    ///     fn deref(&self) -> &Self::Target {
-    ///         todo!()
-    ///     }
-    /// }
-    ///
-    /// fn take_a(_: &dyn A) { }
-    ///
-    /// fn take_b(b: &dyn B) {
-    ///     take_a(b);
-    /// }
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// The dyn upcasting coercion feature adds new coercion rules, taking priority
-    /// over certain other coercion rules, which will cause some behavior change.
-    pub DEREF_INTO_DYN_SUPERTRAIT,
-    Warn,
-    "`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future",
-    @future_incompatible = FutureIncompatibleInfo {
-        reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
-    };
-}
-
-declare_lint! {
     /// The `duplicate_macro_attributes` lint detects when a `#[test]`-like built-in macro
     /// attribute is duplicated on an item. This lint may trigger on `bench`, `cfg_eval`, `test`
     /// and `test_case`.
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 18d37d95a83..5f02bb6c307 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -800,7 +800,7 @@ LLVMRustOptimize(
       auto Plugin = PassPlugin::Load(PluginPath.str());
       if (!Plugin) {
         LLVMRustSetLastError(("Failed to load pass plugin" + PluginPath.str()).c_str());
-        continue;
+        return LLVMRustResult::Failure;
       }
       Plugin->registerPassBuilderCallbacks(PB);
     }
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index d4c457975a8..1a2389c7a84 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -162,7 +162,7 @@ impl CStore {
     pub(crate) fn iter_crate_data(&self) -> impl Iterator<Item = (CrateNum, &CrateMetadata)> {
         self.metas
             .iter_enumerated()
-            .filter_map(|(cnum, data)| data.as_ref().map(|data| (cnum, &**data)))
+            .filter_map(|(cnum, data)| data.as_deref().map(|data| (cnum, data)))
     }
 
     fn push_dependencies_in_postorder(&self, deps: &mut Vec<CrateNum>, cnum: CrateNum) {
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index e5b91d566e5..6f7e6e09ca5 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -692,6 +692,7 @@ pub struct CrateLocationUnknownType<'a> {
     #[primary_span]
     pub span: Span,
     pub path: &'a Path,
+    pub crate_name: Symbol,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 35f9ef92a1c..15546092e41 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -707,6 +707,12 @@ impl<'a> CrateLocator<'a> {
                     loc.original().clone(),
                 ));
             }
+            if !loc.original().is_file() {
+                return Err(CrateError::ExternLocationNotFile(
+                    self.crate_name,
+                    loc.original().clone(),
+                ));
+            }
             let Some(file) = loc.original().file_name().and_then(|s| s.to_str()) else {
                 return Err(CrateError::ExternLocationNotFile(
                     self.crate_name,
@@ -1020,11 +1026,10 @@ impl CrateError {
                     None => String::new(),
                     Some(r) => format!(" which `{}` depends on", r.name),
                 };
-                // FIXME: There are no tests for CrateLocationUnknownType or LibFilenameForm
                 if !locator.crate_rejections.via_filename.is_empty() {
                     let mismatches = locator.crate_rejections.via_filename.iter();
                     for CrateMismatch { path, .. } in mismatches {
-                        sess.emit_err(CrateLocationUnknownType { span, path: &path });
+                        sess.emit_err(CrateLocationUnknownType { span, path: &path, crate_name });
                         sess.emit_err(LibFilenameForm {
                             span,
                             dll_prefix: &locator.dll_prefix,
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 8e80d794a13..ac4b5126190 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -11,7 +11,7 @@ use rustc_data_structures::sync::{Lock, LockGuard, Lrc, OnceCell};
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
 use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro};
-use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
+use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc_hir::diagnostic_items::DiagnosticItems;
@@ -31,7 +31,7 @@ use rustc_session::cstore::{
 use rustc_session::Session;
 use rustc_span::hygiene::{ExpnIndex, MacroKind};
 use rustc_span::source_map::{respan, Spanned};
-use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
 
 use proc_macro::bridge::client::ProcMacro;
@@ -866,12 +866,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
 
         let variant_did =
             if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { None };
-        let ctor_did = data.ctor.map(|index| self.local_def_id(index));
+        let ctor = data.ctor.map(|(kind, index)| (kind, self.local_def_id(index)));
 
         ty::VariantDef::new(
             self.item_name(index),
             variant_did,
-            ctor_did,
+            ctor,
             data.discr,
             self.root
                 .tables
@@ -885,7 +885,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                     vis: self.get_visibility(index),
                 })
                 .collect(),
-            data.ctor_kind,
             adt_kind,
             parent_did,
             false,
@@ -1041,29 +1040,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                 };
 
                 callback(ModChild { ident, res, vis, span, macro_rules });
-
-                // For non-reexport variants add their fictive constructors to children.
-                // Braced variants, unlike structs, generate unusable names in value namespace,
-                // they are reserved for possible future use. It's ok to use the variant's id as
-                // a ctor id since an error will be reported on any use of such resolution anyway.
-                // Reexport lists automatically contain such constructors when necessary.
-                if kind == DefKind::Variant && self.get_ctor_def_id_and_kind(child_index).is_none()
-                {
-                    let ctor_res =
-                        Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive), def_id);
-                    let mut vis = vis;
-                    if vis.is_public() {
-                        // For non-exhaustive variants lower the constructor visibility to
-                        // within the crate. We only need this for fictive constructors,
-                        // for other constructors correct visibilities
-                        // were already encoded in metadata.
-                        let mut attrs = self.get_item_attrs(def_id.index, sess);
-                        if attrs.any(|item| item.has_name(sym::non_exhaustive)) {
-                            vis = ty::Visibility::Restricted(self.local_def_id(CRATE_DEF_INDEX));
-                        }
-                    }
-                    callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false });
-                }
             }
         }
 
@@ -1136,11 +1112,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn get_ctor_def_id_and_kind(self, node_id: DefIndex) -> Option<(DefId, CtorKind)> {
+    fn get_ctor(self, node_id: DefIndex) -> Option<(CtorKind, DefId)> {
         match self.def_kind(node_id) {
             DefKind::Struct | DefKind::Variant => {
                 let vdata = self.root.tables.variant_data.get(self, node_id).unwrap().decode(self);
-                vdata.ctor.map(|index| (self.local_def_id(index), vdata.ctor_kind))
+                vdata.ctor.map(|(kind, index)| (kind, self.local_def_id(index)))
             }
             _ => None,
         }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index f475b0b3981..d96252ba569 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -495,8 +495,8 @@ impl CStore {
         self.get_crate_data(def.krate).get_struct_field_visibilities(def.index)
     }
 
-    pub fn ctor_def_id_and_kind_untracked(&self, def: DefId) -> Option<(DefId, CtorKind)> {
-        self.get_crate_data(def.krate).get_ctor_def_id_and_kind(def.index)
+    pub fn ctor_untracked(&self, def: DefId) -> Option<(CtorKind, DefId)> {
+        self.get_crate_data(def.krate).get_ctor(def.index)
     }
 
     pub fn visibility_untracked(&self, def: DefId) -> Visibility<DefId> {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 76a7fb41e6c..0602b7fc3bd 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1221,9 +1221,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         debug!("EncodeContext::encode_enum_variant_info({:?})", def_id);
 
         let data = VariantData {
-            ctor_kind: variant.ctor_kind,
             discr: variant.discr,
-            ctor: variant.ctor_def_id.map(|did| did.index),
+            ctor: variant.ctor.map(|(kind, def_id)| (kind, def_id.index)),
             is_non_exhaustive: variant.is_field_list_non_exhaustive(),
         };
 
@@ -1233,32 +1232,28 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             assert!(f.did.is_local());
             f.did.index
         }));
-        if variant.ctor_kind == CtorKind::Fn {
+        if let Some((CtorKind::Fn, ctor_def_id)) = variant.ctor {
             // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`.
-            if let Some(ctor_def_id) = variant.ctor_def_id {
-                record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(ctor_def_id));
-            }
+            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(ctor_def_id));
         }
     }
 
     fn encode_enum_variant_ctor(&mut self, def: ty::AdtDef<'tcx>, index: VariantIdx) {
-        let tcx = self.tcx;
         let variant = &def.variant(index);
-        let def_id = variant.ctor_def_id.unwrap();
+        let Some((ctor_kind, def_id)) = variant.ctor else { return };
         debug!("EncodeContext::encode_enum_variant_ctor({:?})", def_id);
 
         // FIXME(eddyb) encode only the `CtorKind` for constructors.
         let data = VariantData {
-            ctor_kind: variant.ctor_kind,
             discr: variant.discr,
-            ctor: Some(def_id.index),
+            ctor: Some((ctor_kind, def_id.index)),
             is_non_exhaustive: variant.is_field_list_non_exhaustive(),
         };
 
         record!(self.tables.variant_data[def_id] <- data);
         self.tables.constness.set(def_id.index, hir::Constness::Const);
-        if variant.ctor_kind == CtorKind::Fn {
-            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
+        if ctor_kind == CtorKind::Fn {
+            record!(self.tables.fn_sig[def_id] <- self.tcx.fn_sig(def_id));
         }
     }
 
@@ -1313,23 +1308,22 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         }
     }
 
-    fn encode_struct_ctor(&mut self, adt_def: ty::AdtDef<'tcx>, def_id: DefId) {
-        debug!("EncodeContext::encode_struct_ctor({:?})", def_id);
-        let tcx = self.tcx;
+    fn encode_struct_ctor(&mut self, adt_def: ty::AdtDef<'tcx>) {
         let variant = adt_def.non_enum_variant();
+        let Some((ctor_kind, def_id)) = variant.ctor else { return };
+        debug!("EncodeContext::encode_struct_ctor({:?})", def_id);
 
         let data = VariantData {
-            ctor_kind: variant.ctor_kind,
             discr: variant.discr,
-            ctor: Some(def_id.index),
+            ctor: Some((ctor_kind, def_id.index)),
             is_non_exhaustive: variant.is_field_list_non_exhaustive(),
         };
 
         record!(self.tables.repr_options[def_id] <- adt_def.repr());
         record!(self.tables.variant_data[def_id] <- data);
         self.tables.constness.set(def_id.index, hir::Constness::Const);
-        if variant.ctor_kind == CtorKind::Fn {
-            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
+        if ctor_kind == CtorKind::Fn {
+            record!(self.tables.fn_sig[def_id] <- self.tcx.fn_sig(def_id));
         }
     }
 
@@ -1550,21 +1544,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 let adt_def = self.tcx.adt_def(def_id);
                 record!(self.tables.repr_options[def_id] <- adt_def.repr());
             }
-            hir::ItemKind::Struct(ref struct_def, _) => {
+            hir::ItemKind::Struct(..) => {
                 let adt_def = self.tcx.adt_def(def_id);
                 record!(self.tables.repr_options[def_id] <- adt_def.repr());
                 self.tables.constness.set(def_id.index, hir::Constness::Const);
 
-                // Encode def_ids for each field and method
-                // for methods, write all the stuff get_trait_method
-                // needs to know
-                let ctor = struct_def.ctor_def_id().map(|ctor_def_id| ctor_def_id.local_def_index);
-
                 let variant = adt_def.non_enum_variant();
                 record!(self.tables.variant_data[def_id] <- VariantData {
-                    ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
-                    ctor,
+                    ctor: variant.ctor.map(|(kind, def_id)| (kind, def_id.index)),
                     is_non_exhaustive: variant.is_field_list_non_exhaustive(),
                 });
             }
@@ -1574,9 +1562,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
                 let variant = adt_def.non_enum_variant();
                 record!(self.tables.variant_data[def_id] <- VariantData {
-                    ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
-                    ctor: None,
+                    ctor: variant.ctor.map(|(kind, def_id)| (kind, def_id.index)),
                     is_non_exhaustive: variant.is_field_list_non_exhaustive(),
                 });
             }
@@ -1629,7 +1616,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     for variant in tcx.adt_def(def_id).variants() {
                         yield variant.def_id.index;
                         // Encode constructors which take a separate slot in value namespace.
-                        if let Some(ctor_def_id) = variant.ctor_def_id {
+                        if let Some(ctor_def_id) = variant.ctor_def_id() {
                             yield ctor_def_id.index;
                         }
                     }
@@ -1672,20 +1659,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         match item.kind {
             hir::ItemKind::Enum(..) => {
                 let def = self.tcx.adt_def(item.owner_id.to_def_id());
-                for (i, variant) in def.variants().iter_enumerated() {
+                for (i, _) in def.variants().iter_enumerated() {
                     self.encode_enum_variant_info(def, i);
-
-                    if let Some(_ctor_def_id) = variant.ctor_def_id {
-                        self.encode_enum_variant_ctor(def, i);
-                    }
+                    self.encode_enum_variant_ctor(def, i);
                 }
             }
-            hir::ItemKind::Struct(ref struct_def, _) => {
+            hir::ItemKind::Struct(..) => {
                 let def = self.tcx.adt_def(item.owner_id.to_def_id());
-                // If the struct has a constructor, encode it.
-                if let Some(ctor_def_id) = struct_def.ctor_def_id() {
-                    self.encode_struct_ctor(def, ctor_def_id.to_def_id());
-                }
+                self.encode_struct_ctor(def);
             }
             hir::ItemKind::Impl { .. } => {
                 for &trait_item_def_id in
@@ -2185,7 +2166,7 @@ impl EncodedMetadata {
 
     #[inline]
     pub fn raw_data(&self) -> &[u8] {
-        self.mmap.as_ref().map(|mmap| mmap.as_ref()).unwrap_or_default()
+        self.mmap.as_deref().unwrap_or_default()
     }
 }
 
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index ba6a3aeb209..3e0b5fa6dd9 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -410,10 +410,9 @@ define_tables! {
 
 #[derive(TyEncodable, TyDecodable)]
 struct VariantData {
-    ctor_kind: CtorKind,
     discr: ty::VariantDiscr,
     /// If this is unit or tuple-variant/struct, then this is the index of the ctor id.
-    ctor: Option<DefIndex>,
+    ctor: Option<(CtorKind, DefIndex)>,
     is_non_exhaustive: bool,
 }
 
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index e7c1abd126e..29fe6110797 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -101,10 +101,8 @@ fixed_size_enum! {
         ( Static(ast::Mutability::Mut)             )
         ( Ctor(CtorOf::Struct, CtorKind::Fn)       )
         ( Ctor(CtorOf::Struct, CtorKind::Const)    )
-        ( Ctor(CtorOf::Struct, CtorKind::Fictive)  )
         ( Ctor(CtorOf::Variant, CtorKind::Fn)      )
         ( Ctor(CtorOf::Variant, CtorKind::Const)   )
-        ( Ctor(CtorOf::Variant, CtorKind::Fictive) )
         ( Macro(MacroKind::Bang)                   )
         ( Macro(MacroKind::Attr)                   )
         ( Macro(MacroKind::Derive)                 )
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index f8aae86fe3d..7bd4b6c0c27 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -6,7 +6,7 @@
 macro_rules! arena_types {
     ($macro:path) => (
         $macro!([
-            [] layout: rustc_target::abi::LayoutS<'tcx>,
+            [] layout: rustc_target::abi::LayoutS<rustc_target::abi::VariantIdx>,
             [] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
             // AdtDef are interned and compared by address
             [decode] adt_def: rustc_middle::ty::AdtDefData,
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index e14ea7be9cf..d4456adf201 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -245,15 +245,15 @@ impl<'hir> Map<'hir> {
             },
             Node::Variant(_) => DefKind::Variant,
             Node::Ctor(variant_data) => {
-                // FIXME(eddyb) is this even possible, if we have a `Node::Ctor`?
-                assert_ne!(variant_data.ctor_hir_id(), None);
-
                 let ctor_of = match self.find(self.get_parent_node(hir_id)) {
                     Some(Node::Item(..)) => def::CtorOf::Struct,
                     Some(Node::Variant(..)) => def::CtorOf::Variant,
                     _ => unreachable!(),
                 };
-                DefKind::Ctor(ctor_of, def::CtorKind::from_hir(variant_data))
+                match variant_data.ctor_kind() {
+                    Some(kind) => DefKind::Ctor(ctor_of, kind),
+                    None => bug!("constructor node without a constructor"),
+                }
             }
             Node::AnonConst(_) => {
                 let inline = match self.find(self.get_parent_node(hir_id)) {
diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index 53c4d926784..12aef66bcf9 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -38,7 +38,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
             tcx.hir().krate_attrs(),
             tcx.sess,
             sym::const_eval_limit,
-            1_000_000,
+            2_000_000,
         ),
     }
 }
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index 3a91522d362..fc08d58cc40 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -4,7 +4,6 @@
 use crate::ty::{DefIdTree, TyCtxt, Visibility};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_hir::def::DefKind;
 use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_span::def_id::LocalDefId;
@@ -142,13 +141,13 @@ impl EffectiveVisibilities {
     pub fn set_public_at_level(
         &mut self,
         id: LocalDefId,
-        default_vis: impl FnOnce() -> Visibility,
+        lazy_private_vis: impl FnOnce() -> Visibility,
         level: Level,
     ) {
         let mut effective_vis = self
             .effective_vis(id)
             .copied()
-            .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis()));
+            .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;
@@ -185,7 +184,6 @@ impl EffectiveVisibilities {
                 );
             }
             let nominal_vis = tcx.visibility(def_id);
-            let def_kind = tcx.opt_def_kind(def_id);
             // FIXME: `rustc_privacy` is not yet updated for the new logic and can set
             // effective visibilities that are larger than the nominal one.
             if !nominal_vis.is_at_least(ev.reachable_through_impl_trait, tcx) && early {
@@ -197,15 +195,15 @@ impl EffectiveVisibilities {
                     nominal_vis
                 );
             }
-            // Fully private items are never put into the table, this is important for performance.
-            // FIXME: Fully private `mod` items are currently put into the table.
-            if ev.reachable_through_impl_trait == private_vis && def_kind != Some(DefKind::Mod) {
-                span_bug!(span, "fully private item in the table {:?}: {:?}", def_id, ev.direct);
-            }
         }
     }
 }
 
+pub trait IntoDefIdTree {
+    type Tree: DefIdTree;
+    fn tree(self) -> Self::Tree;
+}
+
 impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
     pub fn iter(&self) -> impl Iterator<Item = (&Id, &EffectiveVisibility)> {
         self.map.iter()
@@ -215,56 +213,65 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
         self.map.get(&id)
     }
 
-    // `parent_id` is not necessarily a parent in source code tree,
-    // it is the node from which the maximum effective visibility is inherited.
-    pub fn update(
+    // FIXME: Share code with `fn update`.
+    pub fn effective_vis_or_private(
+        &mut self,
+        id: Id,
+        lazy_private_vis: impl FnOnce() -> Visibility,
+    ) -> &EffectiveVisibility {
+        self.map.entry(id).or_insert_with(|| EffectiveVisibility::from_vis(lazy_private_vis()))
+    }
+
+    pub fn update<T: IntoDefIdTree>(
         &mut self,
         id: Id,
         nominal_vis: Visibility,
-        default_vis: Visibility,
-        inherited_eff_vis: Option<EffectiveVisibility>,
+        lazy_private_vis: impl FnOnce(T) -> (Visibility, T),
+        inherited_effective_vis: EffectiveVisibility,
         level: Level,
-        tree: impl DefIdTree,
+        mut into_tree: T,
     ) -> bool {
         let mut changed = false;
-        let mut current_effective_vis = self
-            .map
-            .get(&id)
-            .copied()
-            .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis));
-        if let Some(inherited_effective_vis) = inherited_eff_vis {
-            let mut inherited_effective_vis_at_prev_level =
-                *inherited_effective_vis.at_level(level);
-            let mut calculated_effective_vis = inherited_effective_vis_at_prev_level;
-            for l in Level::all_levels() {
-                if level >= l {
-                    let inherited_effective_vis_at_level = *inherited_effective_vis.at_level(l);
-                    let current_effective_vis_at_level = current_effective_vis.at_level_mut(l);
-                    // effective visibility for id shouldn't be recalculated if
-                    // inherited from parent_id effective visibility isn't changed at next level
-                    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, tree) {
-                                inherited_effective_vis_at_level
-                            } else {
-                                nominal_vis
-                            };
-                    }
-                    // effective visibility can't be decreased at next update call for the
-                    // same id
-                    if *current_effective_vis_at_level != calculated_effective_vis
-                        && calculated_effective_vis
-                            .is_at_least(*current_effective_vis_at_level, tree)
-                    {
-                        changed = true;
-                        *current_effective_vis_at_level = calculated_effective_vis;
-                    }
-                    inherited_effective_vis_at_prev_level = inherited_effective_vis_at_level;
+        let mut current_effective_vis = match self.map.get(&id).copied() {
+            Some(eff_vis) => eff_vis,
+            None => {
+                let private_vis;
+                (private_vis, into_tree) = lazy_private_vis(into_tree);
+                EffectiveVisibility::from_vis(private_vis)
+            }
+        };
+        let tree = into_tree.tree();
+
+        let mut inherited_effective_vis_at_prev_level = *inherited_effective_vis.at_level(level);
+        let mut calculated_effective_vis = inherited_effective_vis_at_prev_level;
+        for l in Level::all_levels() {
+            if level >= l {
+                let inherited_effective_vis_at_level = *inherited_effective_vis.at_level(l);
+                let current_effective_vis_at_level = current_effective_vis.at_level_mut(l);
+                // effective visibility for id shouldn't be recalculated if
+                // inherited from parent_id effective visibility isn't changed at next level
+                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, tree) {
+                            inherited_effective_vis_at_level
+                        } else {
+                            nominal_vis
+                        };
                 }
+                // effective visibility can't be decreased at next update call for the
+                // same id
+                if *current_effective_vis_at_level != calculated_effective_vis
+                    && calculated_effective_vis.is_at_least(*current_effective_vis_at_level, tree)
+                {
+                    changed = true;
+                    *current_effective_vis_at_level = calculated_effective_vis;
+                }
+                inherited_effective_vis_at_prev_level = inherited_effective_vis_at_level;
             }
         }
+
         self.map.insert(id, current_effective_vis);
         changed
     }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 8b70eabb105..364c1b375ae 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -2115,10 +2115,10 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                                 .print_def_path(variant_def.def_id, substs)?
                                 .into_buffer();
 
-                            match variant_def.ctor_kind {
-                                CtorKind::Const => fmt.write_str(&name),
-                                CtorKind::Fn => fmt_tuple(fmt, &name),
-                                CtorKind::Fictive => {
+                            match variant_def.ctor_kind() {
+                                Some(CtorKind::Const) => fmt.write_str(&name),
+                                Some(CtorKind::Fn) => fmt_tuple(fmt, &name),
+                                None => {
                                     let mut struct_fmt = fmt.debug_struct(&name);
                                     for (field, place) in iter::zip(&variant_def.fields, places) {
                                         struct_fmt.field(field.name.as_str(), place);
@@ -2955,14 +2955,14 @@ fn pretty_print_const_value<'tcx>(
                             let cx = cx.print_value_path(variant_def.def_id, substs)?;
                             fmt.write_str(&cx.into_buffer())?;
 
-                            match variant_def.ctor_kind {
-                                CtorKind::Const => {}
-                                CtorKind::Fn => {
+                            match variant_def.ctor_kind() {
+                                Some(CtorKind::Const) => {}
+                                Some(CtorKind::Fn) => {
                                     fmt.write_str("(")?;
                                     comma_sep(fmt, fields)?;
                                     fmt.write_str(")")?;
                                 }
-                                CtorKind::Fictive => {
+                                None => {
                                     fmt.write_str(" {{ ")?;
                                     let mut first = true;
                                     for (field_def, field) in iter::zip(&variant_def.fields, fields)
diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 8be2e2be86b..880632561b9 100644
--- a/compiler/rustc_query_impl/src/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -1,19 +1,22 @@
 //! Defines the set of legal keys that can be used in queries.
 
+use crate::infer::canonical::Canonical;
+use crate::mir;
+use crate::traits;
+use crate::ty::fast_reject::SimplifiedType;
+use crate::ty::subst::{GenericArg, SubstsRef};
+use crate::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::hir_id::{HirId, OwnerId};
-use rustc_middle::infer::canonical::Canonical;
-use rustc_middle::mir;
-use rustc_middle::traits;
-use rustc_middle::ty::fast_reject::SimplifiedType;
-use rustc_middle::ty::subst::{GenericArg, SubstsRef};
-use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
+use rustc_query_system::query::{DefaultCacheSelector, VecCacheSelector};
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 
 /// The `Key` trait controls what types can legally be used as the key
 /// for a query.
-pub trait Key {
+pub trait Key: Sized {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     /// Given an instance of this key, what crate is it referring to?
     /// This is used to find the provider.
     fn query_crate_is_local(&self) -> bool;
@@ -100,6 +103,8 @@ impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
 }
 
 impl Key for CrateNum {
+    type CacheSelector = VecCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         *self == LOCAL_CRATE
@@ -110,6 +115,8 @@ impl Key for CrateNum {
 }
 
 impl Key for OwnerId {
+    type CacheSelector = VecCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -123,6 +130,8 @@ impl Key for OwnerId {
 }
 
 impl Key for LocalDefId {
+    type CacheSelector = VecCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 21097b1fec6..d86bdbd63d8 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -7,6 +7,9 @@
 use crate::ty::{self, print::describe_as_module, TyCtxt};
 use rustc_span::def_id::LOCAL_CRATE;
 
+mod keys;
+pub use keys::Key;
+
 // Each of these queries corresponds to a function pointer field in the
 // `Providers` struct for requesting a value of that type, and a method
 // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index ea7a507d7a4..8bef9dfe099 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -10,7 +10,6 @@
 
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir as hir;
-use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::RangeEnd;
 use rustc_index::newtype_index;
@@ -751,7 +750,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
 
                     // Only for Adt we can have `S {...}`,
                     // which we handle separately here.
-                    if variant.ctor_kind == CtorKind::Fictive {
+                    if variant.ctor.is_none() {
                         write!(f, " {{ ")?;
 
                         let mut printed = 0;
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 1890c0e24bb..536d2872bf0 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -660,6 +660,9 @@ pub enum ImplSource<'tcx, N> {
     /// ImplSource automatically generated for a generator.
     Generator(ImplSourceGeneratorData<'tcx, N>),
 
+    /// ImplSource automatically generated for a generator backing an async future.
+    Future(ImplSourceFutureData<'tcx, N>),
+
     /// ImplSource for a trait alias.
     TraitAlias(ImplSourceTraitAliasData<'tcx, N>),
 
@@ -676,6 +679,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
             ImplSource::AutoImpl(d) => d.nested,
             ImplSource::Closure(c) => c.nested,
             ImplSource::Generator(c) => c.nested,
+            ImplSource::Future(c) => c.nested,
             ImplSource::Object(d) => d.nested,
             ImplSource::FnPointer(d) => d.nested,
             ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
@@ -694,6 +698,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
             ImplSource::AutoImpl(d) => &d.nested,
             ImplSource::Closure(c) => &c.nested,
             ImplSource::Generator(c) => &c.nested,
+            ImplSource::Future(c) => &c.nested,
             ImplSource::Object(d) => &d.nested,
             ImplSource::FnPointer(d) => &d.nested,
             ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
@@ -737,6 +742,11 @@ impl<'tcx, N> ImplSource<'tcx, N> {
                 substs: c.substs,
                 nested: c.nested.into_iter().map(f).collect(),
             }),
+            ImplSource::Future(c) => ImplSource::Future(ImplSourceFutureData {
+                generator_def_id: c.generator_def_id,
+                substs: c.substs,
+                nested: c.nested.into_iter().map(f).collect(),
+            }),
             ImplSource::FnPointer(p) => ImplSource::FnPointer(ImplSourceFnPointerData {
                 fn_ty: p.fn_ty,
                 nested: p.nested.into_iter().map(f).collect(),
@@ -798,6 +808,16 @@ pub struct ImplSourceGeneratorData<'tcx, N> {
 
 #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
 #[derive(TypeFoldable, TypeVisitable)]
+pub struct ImplSourceFutureData<'tcx, N> {
+    pub generator_def_id: DefId,
+    pub substs: SubstsRef<'tcx>,
+    /// Nested obligations. This can be non-empty if the generator
+    /// signature contains associated types.
+    pub nested: Vec<N>,
+}
+
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
+#[derive(TypeFoldable, TypeVisitable)]
 pub struct ImplSourceClosureData<'tcx, N> {
     pub closure_def_id: DefId,
     pub substs: SubstsRef<'tcx>,
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index 85ead3171e7..99bfa477f74 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -131,6 +131,10 @@ pub enum SelectionCandidate<'tcx> {
     /// generated for a generator.
     GeneratorCandidate,
 
+    /// Implementation of a `Future` trait by one of the generator types
+    /// generated for an async construct.
+    FutureCandidate,
+
     /// Implementation of a `Fn`-family trait by one of the anonymous
     /// types generated for a fn pointer type (e.g., `fn(int) -> int`)
     FnPointerCandidate {
diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs
index 7fbd57ac735..735cece8399 100644
--- a/compiler/rustc_middle/src/traits/structural_impls.rs
+++ b/compiler/rustc_middle/src/traits/structural_impls.rs
@@ -15,6 +15,8 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
 
             super::ImplSource::Generator(ref d) => write!(f, "{:?}", d),
 
+            super::ImplSource::Future(ref d) => write!(f, "{:?}", d),
+
             super::ImplSource::FnPointer(ref d) => write!(f, "({:?})", d),
 
             super::ImplSource::DiscriminantKind(ref d) => write!(f, "{:?}", d),
@@ -58,6 +60,16 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceGeneratorData<'tcx, N
     }
 }
 
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceFutureData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "ImplSourceFutureData(generator_def_id={:?}, substs={:?}, nested={:?})",
+            self.generator_def_id, self.substs, self.nested
+        )
+    }
+}
+
 impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceClosureData<'tcx, N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index e6aab30a150..cd147d7e558 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -36,6 +36,11 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
+
+    fn intercrate(&self) -> bool {
+        false
+    }
+
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.param_env
     }
@@ -43,6 +48,10 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
         true
     } // irrelevant
 
+    fn mark_ambiguous(&mut self) {
+        bug!()
+    }
+
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _: ty::Variance,
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 137b59cf6c2..d3d667f6840 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -14,7 +14,7 @@ use rustc_index::vec::{Idx, IndexVec};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::DataTypeKind;
 use rustc_span::symbol::sym;
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{ReprOptions, VariantIdx};
 
 use std::cell::RefCell;
 use std::cmp::Ordering;
@@ -22,9 +22,7 @@ use std::hash::{Hash, Hasher};
 use std::ops::Range;
 use std::str;
 
-use super::{
-    Destructor, FieldDef, GenericPredicates, ReprOptions, Ty, TyCtxt, VariantDef, VariantDiscr,
-};
+use super::{Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, VariantDiscr};
 
 bitflags! {
     #[derive(HashStable, TyEncodable, TyDecodable)]
@@ -230,7 +228,7 @@ impl AdtDefData {
             AdtKind::Struct => AdtFlags::IS_STRUCT,
         };
 
-        if kind == AdtKind::Struct && variants[VariantIdx::new(0)].ctor_def_id.is_some() {
+        if kind == AdtKind::Struct && variants[VariantIdx::new(0)].ctor.is_some() {
             flags |= AdtFlags::HAS_CTOR;
         }
 
@@ -386,11 +384,9 @@ impl<'tcx> AdtDef<'tcx> {
         //    Baz = 3,
         // }
         // ```
-        if self
-            .variants()
-            .iter()
-            .any(|v| matches!(v.discr, VariantDiscr::Explicit(_)) && v.ctor_kind != CtorKind::Const)
-        {
+        if self.variants().iter().any(|v| {
+            matches!(v.discr, VariantDiscr::Explicit(_)) && v.ctor_kind() != Some(CtorKind::Const)
+        }) {
             return false;
         }
         self.variants().iter().all(|v| v.fields.is_empty())
@@ -405,7 +401,7 @@ impl<'tcx> AdtDef<'tcx> {
     pub fn variant_with_ctor_id(self, cid: DefId) -> &'tcx VariantDef {
         self.variants()
             .iter()
-            .find(|v| v.ctor_def_id == Some(cid))
+            .find(|v| v.ctor_def_id() == Some(cid))
             .expect("variant_with_ctor_id: unknown variant")
     }
 
@@ -422,7 +418,7 @@ impl<'tcx> AdtDef<'tcx> {
     pub fn variant_index_with_ctor_id(self, cid: DefId) -> VariantIdx {
         self.variants()
             .iter_enumerated()
-            .find(|(_, v)| v.ctor_def_id == Some(cid))
+            .find(|(_, v)| v.ctor_def_id() == Some(cid))
             .expect("variant_index_with_ctor_id: unknown variant")
             .0
     }
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 0d6c26a5822..273a61c966c 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 hir::LangItem;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -130,11 +131,14 @@ impl<'tcx> ClosureKind {
     }
 
     pub fn to_def_id(&self, tcx: TyCtxt<'_>) -> DefId {
-        match self {
-            ClosureKind::Fn => tcx.lang_items().fn_once_trait().unwrap(),
-            ClosureKind::FnMut => tcx.lang_items().fn_mut_trait().unwrap(),
-            ClosureKind::FnOnce => tcx.lang_items().fn_trait().unwrap(),
-        }
+        tcx.require_lang_item(
+            match self {
+                ClosureKind::Fn => LangItem::Fn,
+                ClosureKind::FnMut => LangItem::FnMut,
+                ClosureKind::FnOnce => LangItem::FnOnce,
+            },
+            None,
+        )
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 8d6ae142314..b5327ad0cec 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -148,7 +148,7 @@ pub struct CtxtInterners<'tcx> {
     const_: InternedSet<'tcx, ConstS<'tcx>>,
     const_allocation: InternedSet<'tcx, Allocation>,
     bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
-    layout: InternedSet<'tcx, LayoutS<'tcx>>,
+    layout: InternedSet<'tcx, LayoutS<VariantIdx>>,
     adt_def: InternedSet<'tcx, AdtDefData>,
 }
 
@@ -1233,7 +1233,7 @@ impl<'tcx> TyCtxt<'tcx> {
             global_ctxt: untracked_resolutions,
             ast_lowering: untracked_resolver_for_lowering,
         } = resolver_outputs;
-        let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| {
+        let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
             s.emit_fatal(err);
         });
         let interners = CtxtInterners::new(arena);
@@ -2244,7 +2244,7 @@ direct_interners! {
     region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>,
     const_: mk_const_internal(ConstS<'tcx>): Const -> Const<'tcx>,
     const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
-    layout: intern_layout(LayoutS<'tcx>): Layout -> Layout<'tcx>,
+    layout: intern_layout(LayoutS<VariantIdx>): Layout -> Layout<'tcx>,
     adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>,
 }
 
@@ -2293,7 +2293,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Given a `ty`, return whether it's an `impl Future<...>`.
     pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool {
         let ty::Opaque(def_id, _) = ty.kind() else { return false };
-        let future_trait = self.lang_items().future_trait().unwrap();
+        let future_trait = self.require_lang_item(LangItem::Future, None);
 
         self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| {
             let ty::PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder() else {
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 3be0bc4defc..1ee4985cf8d 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -42,7 +42,6 @@ where
     ClosureSimplifiedType(D),
     GeneratorSimplifiedType(D),
     GeneratorWitnessSimplifiedType(usize),
-    OpaqueSimplifiedType(D),
     FunctionSimplifiedType(usize),
     PlaceholderSimplifiedType,
 }
@@ -127,7 +126,7 @@ pub fn simplify_type<'tcx>(
             TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType),
             TreatParams::AsInfer => None,
         },
-        ty::Projection(_) => match treat_params {
+        ty::Opaque(..) | ty::Projection(_) => match treat_params {
             // When treating `ty::Param` as a placeholder, projections also
             // don't unify with anything else as long as they are fully normalized.
             //
@@ -138,7 +137,6 @@ pub fn simplify_type<'tcx>(
             }
             TreatParams::AsPlaceholder | TreatParams::AsInfer => None,
         },
-        ty::Opaque(def_id, _) => Some(OpaqueSimplifiedType(def_id)),
         ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)),
         ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None,
     }
@@ -151,8 +149,7 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
             | ForeignSimplifiedType(d)
             | TraitSimplifiedType(d)
             | ClosureSimplifiedType(d)
-            | GeneratorSimplifiedType(d)
-            | OpaqueSimplifiedType(d) => Some(d),
+            | GeneratorSimplifiedType(d) => Some(d),
             _ => None,
         }
     }
@@ -182,7 +179,6 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
             ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
             GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
             GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
-            OpaqueSimplifiedType(d) => OpaqueSimplifiedType(map(d)),
             FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
             PlaceholderSimplifiedType => PlaceholderSimplifiedType,
         }
@@ -229,7 +225,7 @@ impl DeepRejectCtxt {
         match impl_ty.kind() {
             // Start by checking whether the type in the impl may unify with
             // pretty much everything. Just return `true` in that case.
-            ty::Param(_) | ty::Projection(_) | ty::Error(_) => return true,
+            ty::Param(_) | ty::Projection(_) | ty::Error(_) | ty::Opaque(..) => return true,
             // These types only unify with inference variables or their own
             // variant.
             ty::Bool
@@ -247,8 +243,7 @@ impl DeepRejectCtxt {
             | ty::Never
             | ty::Tuple(..)
             | ty::FnPtr(..)
-            | ty::Foreign(..)
-            | ty::Opaque(..) => {}
+            | ty::Foreign(..) => {}
             ty::FnDef(..)
             | ty::Closure(..)
             | ty::Generator(..)
@@ -328,10 +323,7 @@ impl DeepRejectCtxt {
                 _ => false,
             },
 
-            // Opaque types in impls should be forbidden, but that doesn't
-            // stop compilation. So this match arm should never return true
-            // if compilation succeeds.
-            ty::Opaque(..) => matches!(k, ty::Opaque(..)),
+            ty::Opaque(..) => true,
 
             // Impls cannot contain these types as these cannot be named directly.
             ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 7201737be65..ee4b8f91c54 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -259,6 +259,7 @@ impl FlagComputation {
             ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
                 self.add_ty(ty);
             }
+            ty::PredicateKind::Ambiguous => {}
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index c74d6bc3774..488fd567846 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1,8 +1,6 @@
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::ty::normalize_erasing_regions::NormalizationError;
 use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitable};
-use rustc_ast as ast;
-use rustc_attr as attr;
 use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -20,7 +18,6 @@ use std::ops::Bound;
 
 pub trait IntegerExt {
     fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>;
-    fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer;
     fn from_int_ty<C: HasDataLayout>(cx: &C, ity: ty::IntTy) -> Integer;
     fn from_uint_ty<C: HasDataLayout>(cx: &C, uty: ty::UintTy) -> Integer;
     fn repr_discr<'tcx>(
@@ -49,22 +46,6 @@ impl IntegerExt for Integer {
         }
     }
 
-    /// Gets the Integer type from an attr::IntType.
-    fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer {
-        let dl = cx.data_layout();
-
-        match ity {
-            attr::SignedInt(ast::IntTy::I8) | attr::UnsignedInt(ast::UintTy::U8) => I8,
-            attr::SignedInt(ast::IntTy::I16) | attr::UnsignedInt(ast::UintTy::U16) => I16,
-            attr::SignedInt(ast::IntTy::I32) | attr::UnsignedInt(ast::UintTy::U32) => I32,
-            attr::SignedInt(ast::IntTy::I64) | attr::UnsignedInt(ast::UintTy::U64) => I64,
-            attr::SignedInt(ast::IntTy::I128) | attr::UnsignedInt(ast::UintTy::U128) => I128,
-            attr::SignedInt(ast::IntTy::Isize) | attr::UnsignedInt(ast::UintTy::Usize) => {
-                dl.ptr_sized_integer()
-            }
-        }
-    }
-
     fn from_int_ty<C: HasDataLayout>(cx: &C, ity: ty::IntTy) -> Integer {
         match ity {
             ty::IntTy::I8 => I8,
@@ -237,6 +218,18 @@ pub struct LayoutCx<'tcx, C> {
     pub param_env: ty::ParamEnv<'tcx>,
 }
 
+impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> {
+    type TargetDataLayoutRef = &'tcx TargetDataLayout;
+
+    fn delay_bug(&self, txt: &str) {
+        self.tcx.sess.delay_span_bug(DUMMY_SP, txt);
+    }
+
+    fn current_data_layout(&self) -> Self::TargetDataLayoutRef {
+        &self.tcx.data_layout
+    }
+}
+
 /// Type size "skeleton", i.e., the only information determining a type's size.
 /// While this is conservative, (aside from constant sizes, only pointers,
 /// newtypes thereof and null pointer optimized enums are allowed), it is
@@ -610,7 +603,7 @@ where
                 })
             }
 
-            Variants::Multiple { ref variants, .. } => variants[variant_index],
+            Variants::Multiple { ref variants, .. } => cx.tcx().intern_layout(variants[variant_index].clone()),
         };
 
         assert_eq!(*layout.variants(), Variants::Single { index: variant_index });
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 8bac76d559f..9d778ff2fb6 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -48,7 +48,8 @@ use rustc_session::cstore::CrateStoreDyn;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{ExpnId, Span};
-use rustc_target::abi::{Align, VariantIdx};
+use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx};
+pub use rustc_target::abi::{ReprFlags, ReprOptions};
 pub use subst::*;
 pub use vtable::*;
 
@@ -620,6 +621,7 @@ impl<'tcx> Predicate<'tcx> {
             | PredicateKind::Coerce(_)
             | PredicateKind::ConstEvaluatable(_)
             | PredicateKind::ConstEquate(_, _)
+            | PredicateKind::Ambiguous
             | PredicateKind::TypeWellFormedFromEnv(_) => true,
         }
     }
@@ -702,6 +704,10 @@ pub enum PredicateKind<'tcx> {
     ///
     /// Only used for Chalk.
     TypeWellFormedFromEnv(Ty<'tcx>),
+
+    /// A marker predicate that is always ambiguous.
+    /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous.
+    Ambiguous,
 }
 
 /// The crate outlives map is computed during typeck and contains the
@@ -1186,6 +1192,7 @@ impl<'tcx> Predicate<'tcx> {
             | PredicateKind::TypeOutlives(..)
             | PredicateKind::ConstEvaluatable(..)
             | PredicateKind::ConstEquate(..)
+            | PredicateKind::Ambiguous
             | PredicateKind::TypeWellFormedFromEnv(..) => None,
         }
     }
@@ -1204,6 +1211,7 @@ impl<'tcx> Predicate<'tcx> {
             | PredicateKind::TypeOutlives(..)
             | PredicateKind::ConstEvaluatable(..)
             | PredicateKind::ConstEquate(..)
+            | PredicateKind::Ambiguous
             | PredicateKind::TypeWellFormedFromEnv(..) => None,
         }
     }
@@ -1222,6 +1230,7 @@ impl<'tcx> Predicate<'tcx> {
             | PredicateKind::ClosureKind(..)
             | PredicateKind::ConstEvaluatable(..)
             | PredicateKind::ConstEquate(..)
+            | PredicateKind::Ambiguous
             | PredicateKind::TypeWellFormedFromEnv(..) => None,
         }
     }
@@ -1812,15 +1821,13 @@ pub struct VariantDef {
     pub def_id: DefId,
     /// `DefId` that identifies the variant's constructor.
     /// If this variant is a struct variant, then this is `None`.
-    pub ctor_def_id: Option<DefId>,
+    pub ctor: Option<(CtorKind, DefId)>,
     /// Variant or struct name.
     pub name: Symbol,
     /// Discriminant of this variant.
     pub discr: VariantDiscr,
     /// Fields of this variant.
     pub fields: Vec<FieldDef>,
-    /// Type of constructor of variant.
-    pub ctor_kind: CtorKind,
     /// Flags of the variant (e.g. is field list non-exhaustive)?
     flags: VariantFlags,
 }
@@ -1845,19 +1852,18 @@ impl VariantDef {
     pub fn new(
         name: Symbol,
         variant_did: Option<DefId>,
-        ctor_def_id: Option<DefId>,
+        ctor: Option<(CtorKind, DefId)>,
         discr: VariantDiscr,
         fields: Vec<FieldDef>,
-        ctor_kind: CtorKind,
         adt_kind: AdtKind,
         parent_did: DefId,
         recovered: bool,
         is_field_list_non_exhaustive: bool,
     ) -> Self {
         debug!(
-            "VariantDef::new(name = {:?}, variant_did = {:?}, ctor_def_id = {:?}, discr = {:?},
-             fields = {:?}, ctor_kind = {:?}, adt_kind = {:?}, parent_did = {:?})",
-            name, variant_did, ctor_def_id, discr, fields, ctor_kind, adt_kind, parent_did,
+            "VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?},
+             fields = {:?}, adt_kind = {:?}, parent_did = {:?})",
+            name, variant_did, ctor, discr, fields, adt_kind, parent_did,
         );
 
         let mut flags = VariantFlags::NO_VARIANT_FLAGS;
@@ -1869,15 +1875,7 @@ impl VariantDef {
             flags |= VariantFlags::IS_RECOVERED;
         }
 
-        VariantDef {
-            def_id: variant_did.unwrap_or(parent_did),
-            ctor_def_id,
-            name,
-            discr,
-            fields,
-            ctor_kind,
-            flags,
-        }
+        VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, name, discr, fields, flags }
     }
 
     /// Is this field list non-exhaustive?
@@ -1896,6 +1894,16 @@ impl VariantDef {
     pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
         Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
     }
+
+    #[inline]
+    pub fn ctor_kind(&self) -> Option<CtorKind> {
+        self.ctor.map(|(kind, _)| kind)
+    }
+
+    #[inline]
+    pub fn ctor_def_id(&self) -> Option<DefId> {
+        self.ctor.map(|(_, def_id)| def_id)
+    }
 }
 
 impl PartialEq for VariantDef {
@@ -1908,26 +1916,8 @@ impl PartialEq for VariantDef {
         // definition of `VariantDef` changes, a compile-error will be produced,
         // reminding us to revisit this assumption.
 
-        let Self {
-            def_id: lhs_def_id,
-            ctor_def_id: _,
-            name: _,
-            discr: _,
-            fields: _,
-            ctor_kind: _,
-            flags: _,
-        } = &self;
-
-        let Self {
-            def_id: rhs_def_id,
-            ctor_def_id: _,
-            name: _,
-            discr: _,
-            fields: _,
-            ctor_kind: _,
-            flags: _,
-        } = other;
-
+        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
     }
 }
@@ -1944,9 +1934,7 @@ impl Hash for VariantDef {
         // of `VariantDef` changes, a compile-error will be produced, reminding
         // us to revisit this assumption.
 
-        let Self { def_id, ctor_def_id: _, name: _, discr: _, fields: _, ctor_kind: _, flags: _ } =
-            &self;
-
+        let Self { def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
         def_id.hash(s)
     }
 }
@@ -2007,163 +1995,6 @@ impl Hash for FieldDef {
     }
 }
 
-bitflags! {
-    #[derive(TyEncodable, TyDecodable, Default, HashStable)]
-    pub struct ReprFlags: u8 {
-        const IS_C               = 1 << 0;
-        const IS_SIMD            = 1 << 1;
-        const IS_TRANSPARENT     = 1 << 2;
-        // Internal only for now. If true, don't reorder fields.
-        const IS_LINEAR          = 1 << 3;
-        // If true, the type's layout can be randomized using
-        // the seed stored in `ReprOptions.layout_seed`
-        const RANDOMIZE_LAYOUT   = 1 << 4;
-        // Any of these flags being set prevent field reordering optimisation.
-        const IS_UNOPTIMISABLE   = ReprFlags::IS_C.bits
-                                 | ReprFlags::IS_SIMD.bits
-                                 | ReprFlags::IS_LINEAR.bits;
-    }
-}
-
-/// Represents the repr options provided by the user,
-#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Default, HashStable)]
-pub struct ReprOptions {
-    pub int: Option<attr::IntType>,
-    pub align: Option<Align>,
-    pub pack: Option<Align>,
-    pub flags: ReprFlags,
-    /// The seed to be used for randomizing a type's layout
-    ///
-    /// Note: This could technically be a `[u8; 16]` (a `u128`) which would
-    /// be the "most accurate" hash as it'd encompass the item and crate
-    /// hash without loss, but it does pay the price of being larger.
-    /// Everything's a tradeoff, a `u64` seed should be sufficient for our
-    /// purposes (primarily `-Z randomize-layout`)
-    pub field_shuffle_seed: u64,
-}
-
-impl ReprOptions {
-    pub fn new(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions {
-        let mut flags = ReprFlags::empty();
-        let mut size = None;
-        let mut max_align: Option<Align> = None;
-        let mut min_pack: Option<Align> = None;
-
-        // Generate a deterministically-derived seed from the item's path hash
-        // to allow for cross-crate compilation to actually work
-        let mut field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash();
-
-        // If the user defined a custom seed for layout randomization, xor the item's
-        // path hash with the user defined seed, this will allowing determinism while
-        // still allowing users to further randomize layout generation for e.g. fuzzing
-        if let Some(user_seed) = tcx.sess.opts.unstable_opts.layout_seed {
-            field_shuffle_seed ^= user_seed;
-        }
-
-        for attr in tcx.get_attrs(did, sym::repr) {
-            for r in attr::parse_repr_attr(&tcx.sess, attr) {
-                flags.insert(match r {
-                    attr::ReprC => ReprFlags::IS_C,
-                    attr::ReprPacked(pack) => {
-                        let pack = Align::from_bytes(pack as u64).unwrap();
-                        min_pack = Some(if let Some(min_pack) = min_pack {
-                            min_pack.min(pack)
-                        } else {
-                            pack
-                        });
-                        ReprFlags::empty()
-                    }
-                    attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
-                    attr::ReprSimd => ReprFlags::IS_SIMD,
-                    attr::ReprInt(i) => {
-                        size = Some(i);
-                        ReprFlags::empty()
-                    }
-                    attr::ReprAlign(align) => {
-                        max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap()));
-                        ReprFlags::empty()
-                    }
-                });
-            }
-        }
-
-        // If `-Z randomize-layout` was enabled for the type definition then we can
-        // consider performing layout randomization
-        if tcx.sess.opts.unstable_opts.randomize_layout {
-            flags.insert(ReprFlags::RANDOMIZE_LAYOUT);
-        }
-
-        // This is here instead of layout because the choice must make it into metadata.
-        if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) {
-            flags.insert(ReprFlags::IS_LINEAR);
-        }
-
-        Self { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
-    }
-
-    #[inline]
-    pub fn simd(&self) -> bool {
-        self.flags.contains(ReprFlags::IS_SIMD)
-    }
-
-    #[inline]
-    pub fn c(&self) -> bool {
-        self.flags.contains(ReprFlags::IS_C)
-    }
-
-    #[inline]
-    pub fn packed(&self) -> bool {
-        self.pack.is_some()
-    }
-
-    #[inline]
-    pub fn transparent(&self) -> bool {
-        self.flags.contains(ReprFlags::IS_TRANSPARENT)
-    }
-
-    #[inline]
-    pub fn linear(&self) -> bool {
-        self.flags.contains(ReprFlags::IS_LINEAR)
-    }
-
-    /// Returns the discriminant type, given these `repr` options.
-    /// This must only be called on enums!
-    pub fn discr_type(&self) -> attr::IntType {
-        self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize))
-    }
-
-    /// Returns `true` if this `#[repr()]` should inhabit "smart enum
-    /// layout" optimizations, such as representing `Foo<&T>` as a
-    /// single pointer.
-    pub fn inhibit_enum_layout_opt(&self) -> bool {
-        self.c() || self.int.is_some()
-    }
-
-    /// Returns `true` if this `#[repr()]` should inhibit struct field reordering
-    /// optimizations, such as with `repr(C)`, `repr(packed(1))`, or `repr(<int>)`.
-    pub fn inhibit_struct_field_reordering_opt(&self) -> bool {
-        if let Some(pack) = self.pack {
-            if pack.bytes() == 1 {
-                return true;
-            }
-        }
-
-        self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some()
-    }
-
-    /// Returns `true` if this type is valid for reordering and `-Z randomize-layout`
-    /// was enabled for its declaration crate
-    pub fn can_randomize_type_layout(&self) -> bool {
-        !self.inhibit_struct_field_reordering_opt()
-            && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT)
-    }
-
-    /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations.
-    pub fn inhibit_union_abi_opt(&self) -> bool {
-        self.c()
-    }
-}
-
 impl<'tcx> FieldDef {
     /// Returns the type of this field. The resulting type is not normalized. The `subst` is
     /// typically obtained via the second field of [`TyKind::Adt`].
@@ -2231,6 +2062,81 @@ impl<'tcx> TyCtxt<'tcx> {
             .filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value())
     }
 
+    pub fn repr_options_of_def(self, did: DefId) -> ReprOptions {
+        let mut flags = ReprFlags::empty();
+        let mut size = None;
+        let mut max_align: Option<Align> = None;
+        let mut min_pack: Option<Align> = None;
+
+        // Generate a deterministically-derived seed from the item's path hash
+        // to allow for cross-crate compilation to actually work
+        let mut field_shuffle_seed = self.def_path_hash(did).0.to_smaller_hash();
+
+        // If the user defined a custom seed for layout randomization, xor the item's
+        // path hash with the user defined seed, this will allowing determinism while
+        // still allowing users to further randomize layout generation for e.g. fuzzing
+        if let Some(user_seed) = self.sess.opts.unstable_opts.layout_seed {
+            field_shuffle_seed ^= user_seed;
+        }
+
+        for attr in self.get_attrs(did, sym::repr) {
+            for r in attr::parse_repr_attr(&self.sess, attr) {
+                flags.insert(match r {
+                    attr::ReprC => ReprFlags::IS_C,
+                    attr::ReprPacked(pack) => {
+                        let pack = Align::from_bytes(pack as u64).unwrap();
+                        min_pack = Some(if let Some(min_pack) = min_pack {
+                            min_pack.min(pack)
+                        } else {
+                            pack
+                        });
+                        ReprFlags::empty()
+                    }
+                    attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
+                    attr::ReprSimd => ReprFlags::IS_SIMD,
+                    attr::ReprInt(i) => {
+                        size = Some(match i {
+                            attr::IntType::SignedInt(x) => match x {
+                                ast::IntTy::Isize => IntegerType::Pointer(true),
+                                ast::IntTy::I8 => IntegerType::Fixed(Integer::I8, true),
+                                ast::IntTy::I16 => IntegerType::Fixed(Integer::I16, true),
+                                ast::IntTy::I32 => IntegerType::Fixed(Integer::I32, true),
+                                ast::IntTy::I64 => IntegerType::Fixed(Integer::I64, true),
+                                ast::IntTy::I128 => IntegerType::Fixed(Integer::I128, true),
+                            },
+                            attr::IntType::UnsignedInt(x) => match x {
+                                ast::UintTy::Usize => IntegerType::Pointer(false),
+                                ast::UintTy::U8 => IntegerType::Fixed(Integer::I8, false),
+                                ast::UintTy::U16 => IntegerType::Fixed(Integer::I16, false),
+                                ast::UintTy::U32 => IntegerType::Fixed(Integer::I32, false),
+                                ast::UintTy::U64 => IntegerType::Fixed(Integer::I64, false),
+                                ast::UintTy::U128 => IntegerType::Fixed(Integer::I128, false),
+                            },
+                        });
+                        ReprFlags::empty()
+                    }
+                    attr::ReprAlign(align) => {
+                        max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap()));
+                        ReprFlags::empty()
+                    }
+                });
+            }
+        }
+
+        // If `-Z randomize-layout` was enabled for the type definition then we can
+        // consider performing layout randomization
+        if self.sess.opts.unstable_opts.randomize_layout {
+            flags.insert(ReprFlags::RANDOMIZE_LAYOUT);
+        }
+
+        // This is here instead of layout because the choice must make it into metadata.
+        if !self.consider_optimizing(|| format!("Reorder fields of {:?}", self.def_path_str(did))) {
+            flags.insert(ReprFlags::IS_LINEAR);
+        }
+
+        ReprOptions { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
+    }
+
     /// Look up the name of a definition across crates. This does not look at HIR.
     pub fn opt_item_name(self, def_id: DefId) -> Option<Symbol> {
         if let Some(cnum) = def_id.as_crate_root() {
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index a0c076cbbb2..c54edf10c2d 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -11,6 +11,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
 use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
+use rustc_hir::LangItem;
 use rustc_session::config::TrimmedDefPaths;
 use rustc_session::cstore::{ExternCrate, ExternCrateSource};
 use rustc_session::Limit;
@@ -680,6 +681,17 @@ pub trait PrettyPrinter<'tcx>:
             }
             ty::Str => p!("str"),
             ty::Generator(did, substs, movability) => {
+                // FIXME(swatinem): async constructs used to be pretty printed
+                // as `impl Future` previously due to the `from_generator` wrapping.
+                // lets special case this here for now to avoid churn in diagnostics.
+                let generator_kind = self.tcx().generator_kind(did);
+                if matches!(generator_kind, Some(hir::GeneratorKind::Async(..))) {
+                    let return_ty = substs.as_generator().return_ty();
+                    p!(write("impl Future<Output = {}>", return_ty));
+
+                    return Ok(self);
+                }
+
                 p!(write("["));
                 match movability {
                     hir::Movability::Movable => {}
@@ -889,7 +901,7 @@ pub trait PrettyPrinter<'tcx>:
                                 // Group the return ty with its def id, if we had one.
                                 entry
                                     .return_ty
-                                    .map(|ty| (tcx.lang_items().fn_once_output().unwrap(), ty)),
+                                    .map(|ty| (tcx.require_lang_item(LangItem::FnOnce, None), ty)),
                             );
                         }
                         if let Some(trait_ref) = entry.fn_mut_trait_ref {
@@ -1487,12 +1499,12 @@ pub trait PrettyPrinter<'tcx>:
                             contents.variant.expect("destructed const of adt without variant idx");
                         let variant_def = &def.variant(variant_idx);
                         p!(print_value_path(variant_def.def_id, substs));
-                        match variant_def.ctor_kind {
-                            CtorKind::Const => {}
-                            CtorKind::Fn => {
+                        match variant_def.ctor_kind() {
+                            Some(CtorKind::Const) => {}
+                            Some(CtorKind::Fn) => {
                                 p!("(", comma_sep(fields), ")");
                             }
-                            CtorKind::Fictive => {
+                            None => {
                                 p!(" {{ ");
                                 let mut first = true;
                                 for (field_def, field) in iter::zip(&variant_def.fields, fields) {
@@ -2703,6 +2715,7 @@ define_print_and_forward_display! {
             ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
                 p!("the type `", print(ty), "` is found in the environment")
             }
+            ty::PredicateKind::Ambiguous => p!("ambiguous"),
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index ec90590ada2..0f62da9992f 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -15,6 +15,7 @@ use crate::mir::interpret::{
 };
 use crate::mir::interpret::{LitToConstError, LitToConstInput};
 use crate::mir::mono::CodegenUnit;
+use crate::query::Key;
 use crate::thir;
 use crate::traits::query::{
     CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
@@ -121,10 +122,10 @@ macro_rules! query_helper_param_ty {
 
 macro_rules! query_storage {
     ([][$K:ty, $V:ty]) => {
-        <DefaultCacheSelector as CacheSelector<$K, $V>>::Cache
+        <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache
     };
     ([(arena_cache) $($rest:tt)*][$K:ty, $V:ty]) => {
-        <ArenaCacheSelector<'tcx> as CacheSelector<$K, $V>>::Cache
+        <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::ArenaCache
     };
     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
         query_storage!([$($modifiers)*][$($args)*])
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 0adc700586d..3d47b71b7ce 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -23,6 +23,8 @@ pub enum Cause {
 pub trait TypeRelation<'tcx>: Sized {
     fn tcx(&self) -> TyCtxt<'tcx>;
 
+    fn intercrate(&self) -> bool;
+
     fn param_env(&self) -> ty::ParamEnv<'tcx>;
 
     /// Returns a static string we can use for printouts.
@@ -32,6 +34,9 @@ pub trait TypeRelation<'tcx>: Sized {
     /// relation. Just affects error messages.
     fn a_is_expected(&self) -> bool;
 
+    /// Used during coherence. If called, must emit an always-ambiguous obligation.
+    fn mark_ambiguous(&mut self);
+
     fn with_cause<F, R>(&mut self, _cause: Cause, f: F) -> R
     where
         F: FnOnce(&mut Self) -> R,
@@ -562,16 +567,23 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
         (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
             if a_def_id == b_def_id =>
         {
-            let opt_variances = tcx.variances_of(a_def_id);
-            let substs = relate_substs_with_variances(
-                relation,
-                a_def_id,
-                opt_variances,
-                a_substs,
-                b_substs,
-                false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
-            )?;
-            Ok(tcx.mk_opaque(a_def_id, substs))
+            if relation.intercrate() {
+                // During coherence, opaque types should be treated as equal to each other, even if their generic params
+                // differ, as they could resolve to the same hidden type, even for different generic params.
+                relation.mark_ambiguous();
+                Ok(a)
+            } else {
+                let opt_variances = tcx.variances_of(a_def_id);
+                let substs = relate_substs_with_variances(
+                    relation,
+                    a_def_id,
+                    opt_variances,
+                    a_substs,
+                    b_substs,
+                    false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
+                )?;
+                Ok(tcx.mk_opaque(a_def_id, substs))
+            }
         }
 
         _ => Err(TypeError::Sorts(expected_found(relation, a, b))),
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 6be8fdd7cd7..64b4fd11762 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -173,6 +173,7 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
             ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
                 write!(f, "TypeWellFormedFromEnv({:?})", ty)
             }
+            ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"),
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index db18558e947..e7a751fa0af 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -17,6 +17,7 @@ use rustc_data_structures::captures::Captures;
 use rustc_data_structures::intern::Interned;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::LangItem;
 use rustc_index::vec::Idx;
 use rustc_macros::HashStable;
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -2108,7 +2109,7 @@ impl<'tcx> Ty<'tcx> {
 
             ty::Str | ty::Slice(_) => (tcx.types.usize, false),
             ty::Dynamic(..) => {
-                let dyn_metadata = tcx.lang_items().dyn_metadata().unwrap();
+                let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
                 (tcx.bound_type_of(dyn_metadata).subst(tcx, &[tail.into()]), false)
             },
 
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index f72e236eda1..6561c4c278d 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -8,8 +8,6 @@ use crate::ty::{
 };
 use crate::ty::{GenericArgKind, SubstsRef};
 use rustc_apfloat::Float as _;
-use rustc_ast as ast;
-use rustc_attr::{self as attr, SignedInt, UnsignedInt};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_errors::ErrorGuaranteed;
@@ -19,7 +17,7 @@ use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_macros::HashStable;
 use rustc_span::{sym, DUMMY_SP};
-use rustc_target::abi::{Integer, Size, TargetDataLayout};
+use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout};
 use rustc_target::spec::abi::Abi;
 use smallvec::SmallVec;
 use std::{fmt, iter};
@@ -104,21 +102,12 @@ pub trait IntTypeExt {
     fn initial_discriminant<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Discr<'tcx>;
 }
 
-impl IntTypeExt for attr::IntType {
+impl IntTypeExt for IntegerType {
     fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
-        match *self {
-            SignedInt(ast::IntTy::I8) => tcx.types.i8,
-            SignedInt(ast::IntTy::I16) => tcx.types.i16,
-            SignedInt(ast::IntTy::I32) => tcx.types.i32,
-            SignedInt(ast::IntTy::I64) => tcx.types.i64,
-            SignedInt(ast::IntTy::I128) => tcx.types.i128,
-            SignedInt(ast::IntTy::Isize) => tcx.types.isize,
-            UnsignedInt(ast::UintTy::U8) => tcx.types.u8,
-            UnsignedInt(ast::UintTy::U16) => tcx.types.u16,
-            UnsignedInt(ast::UintTy::U32) => tcx.types.u32,
-            UnsignedInt(ast::UintTy::U64) => tcx.types.u64,
-            UnsignedInt(ast::UintTy::U128) => tcx.types.u128,
-            UnsignedInt(ast::UintTy::Usize) => tcx.types.usize,
+        match self {
+            IntegerType::Pointer(true) => tcx.types.isize,
+            IntegerType::Pointer(false) => tcx.types.usize,
+            IntegerType::Fixed(i, s) => i.to_ty(tcx, *s),
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 5e366ef703f..b04afe549ac 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -97,10 +97,10 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
     }
     fn error_reported(&self) -> Result<(), ErrorGuaranteed> {
         if self.references_error() {
-            if let Some(reported) = ty::tls::with(|tcx| tcx.sess.has_errors()) {
+            if let Some(reported) = ty::tls::with(|tcx| tcx.sess.is_compilation_going_to_fail()) {
                 Err(reported)
             } else {
-                bug!("expect tcx.sess.has_errors return true");
+                bug!("expect tcx.sess.is_compilation_going_to_fail return `Some`");
             }
         } else {
             Ok(())
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index db05592ed0e..49d7136a2f1 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -1,4 +1,3 @@
-use crate::build::matches::ArmHasGuard;
 use crate::build::ForGuard::OutsideGuard;
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use rustc_middle::middle::region::Scope;
@@ -231,7 +230,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                         visibility_scope,
                                         remainder_span,
                                         pattern,
-                                        ArmHasGuard(false),
+                                        None,
                                         Some((None, initializer_span)),
                                     );
                                     this.visit_primary_bindings(
@@ -308,7 +307,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                             visibility_scope,
                                             remainder_span,
                                             pattern,
-                                            ArmHasGuard(false),
+                                            None,
                                             Some((None, initializer_span)),
                                         );
                                         this.expr_into_pattern(block, &pattern, init)
@@ -324,7 +323,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                 visibility_scope,
                                 remainder_span,
                                 pattern,
-                                ArmHasGuard(false),
+                                None,
                                 None,
                             );
                             block.unit()
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 396782d45d2..edd52728626 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -65,7 +65,7 @@ pub(crate) enum PlaceBase {
 
 /// `PlaceBuilder` is used to create places during MIR construction. It allows you to "build up" a
 /// place by pushing more and more projections onto the end, and then convert the final set into a
-/// place using the `into_place` method.
+/// place using the `to_place` method.
 ///
 /// This is used internally when building a place for an expression like `a.b.c`. The fields `b`
 /// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
@@ -167,59 +167,54 @@ fn find_capture_matching_projections<'a, 'tcx>(
     })
 }
 
-/// Takes a PlaceBuilder and resolves the upvar (if any) within it, so that the
-/// `PlaceBuilder` now starts from `PlaceBase::Local`.
-///
-/// Returns a Result with the error being the PlaceBuilder (`from_builder`) that was not found.
+/// Takes an upvar place and tries to resolve it into a `PlaceBuilder`
+/// with `PlaceBase::Local`
 #[instrument(level = "trace", skip(cx), ret)]
 fn to_upvars_resolved_place_builder<'tcx>(
-    from_builder: PlaceBuilder<'tcx>,
     cx: &Builder<'_, 'tcx>,
-) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
-    match from_builder.base {
-        PlaceBase::Local(_) => Ok(from_builder),
-        PlaceBase::Upvar { var_hir_id, closure_def_id } => {
-            let Some((capture_index, capture)) =
-                find_capture_matching_projections(
-                    &cx.upvars,
-                    var_hir_id,
-                    &from_builder.projection,
-                ) else {
-                let closure_span = cx.tcx.def_span(closure_def_id);
-                if !enable_precise_capture(cx.tcx, closure_span) {
-                    bug!(
-                        "No associated capture found for {:?}[{:#?}] even though \
-                            capture_disjoint_fields isn't enabled",
-                        var_hir_id,
-                        from_builder.projection
-                    )
-                } else {
-                    debug!(
-                        "No associated capture found for {:?}[{:#?}]",
-                        var_hir_id, from_builder.projection,
-                    );
-                }
-                return Err(from_builder);
-            };
+    var_hir_id: LocalVarId,
+    closure_def_id: LocalDefId,
+    projection: &[PlaceElem<'tcx>],
+) -> Option<PlaceBuilder<'tcx>> {
+    let Some((capture_index, capture)) =
+        find_capture_matching_projections(
+            &cx.upvars,
+            var_hir_id,
+            &projection,
+        ) else {
+        let closure_span = cx.tcx.def_span(closure_def_id);
+        if !enable_precise_capture(cx.tcx, closure_span) {
+            bug!(
+                "No associated capture found for {:?}[{:#?}] even though \
+                    capture_disjoint_fields isn't enabled",
+                var_hir_id,
+                projection
+            )
+        } else {
+            debug!(
+                "No associated capture found for {:?}[{:#?}]",
+                var_hir_id, projection,
+            );
+        }
+        return None;
+    };
 
-            // Access the capture by accessing the field within the Closure struct.
-            let capture_info = &cx.upvars[capture_index];
+    // Access the capture by accessing the field within the Closure struct.
+    let capture_info = &cx.upvars[capture_index];
 
-            let mut upvar_resolved_place_builder = PlaceBuilder::from(capture_info.use_place);
+    let mut upvar_resolved_place_builder = PlaceBuilder::from(capture_info.use_place);
 
-            // We used some of the projections to build the capture itself,
-            // now we apply the remaining to the upvar resolved place.
-            trace!(?capture.captured_place, ?from_builder.projection);
-            let remaining_projections = strip_prefix(
-                capture.captured_place.place.base_ty,
-                from_builder.projection,
-                &capture.captured_place.place.projections,
-            );
-            upvar_resolved_place_builder.projection.extend(remaining_projections);
+    // We used some of the projections to build the capture itself,
+    // now we apply the remaining to the upvar resolved place.
+    trace!(?capture.captured_place, ?projection);
+    let remaining_projections = strip_prefix(
+        capture.captured_place.place.base_ty,
+        projection,
+        &capture.captured_place.place.projections,
+    );
+    upvar_resolved_place_builder.projection.extend(remaining_projections);
 
-            Ok(upvar_resolved_place_builder)
-        }
-    }
+    Some(upvar_resolved_place_builder)
 }
 
 /// Returns projections remaining after stripping an initial prefix of HIR
@@ -228,13 +223,14 @@ fn to_upvars_resolved_place_builder<'tcx>(
 /// Supports only HIR projection kinds that represent a path that might be
 /// captured by a closure or a generator, i.e., an `Index` or a `Subslice`
 /// projection kinds are unsupported.
-fn strip_prefix<'tcx>(
+fn strip_prefix<'a, 'tcx>(
     mut base_ty: Ty<'tcx>,
-    projections: Vec<PlaceElem<'tcx>>,
+    projections: &'a [PlaceElem<'tcx>],
     prefix_projections: &[HirProjection<'tcx>],
-) -> impl Iterator<Item = PlaceElem<'tcx>> {
+) -> impl Iterator<Item = PlaceElem<'tcx>> + 'a {
     let mut iter = projections
-        .into_iter()
+        .iter()
+        .copied()
         // Filter out opaque casts, they are unnecessary in the prefix.
         .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(..)));
     for projection in prefix_projections {
@@ -258,21 +254,21 @@ fn strip_prefix<'tcx>(
 }
 
 impl<'tcx> PlaceBuilder<'tcx> {
-    pub(in crate::build) fn into_place(self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> {
-        if let PlaceBase::Local(local) = self.base {
-            Place { local, projection: cx.tcx.intern_place_elems(&self.projection) }
-        } else {
-            self.expect_upvars_resolved(cx).into_place(cx)
-        }
+    pub(in crate::build) fn to_place(&self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> {
+        self.try_to_place(cx).unwrap()
     }
 
-    fn expect_upvars_resolved(self, cx: &Builder<'_, 'tcx>) -> PlaceBuilder<'tcx> {
-        to_upvars_resolved_place_builder(self, cx).unwrap()
+    /// Creates a `Place` or returns `None` if an upvar cannot be resolved
+    pub(in crate::build) fn try_to_place(&self, cx: &Builder<'_, 'tcx>) -> Option<Place<'tcx>> {
+        let resolved = self.resolve_upvar(cx);
+        let builder = resolved.as_ref().unwrap_or(self);
+        let PlaceBase::Local(local) = builder.base else { return None };
+        let projection = cx.tcx.intern_place_elems(&builder.projection);
+        Some(Place { local, projection })
     }
 
     /// Attempts to resolve the `PlaceBuilder`.
-    /// On success, it will return the resolved `PlaceBuilder`.
-    /// On failure, it will return itself.
+    /// Returns `None` if this is not an upvar.
     ///
     /// Upvars resolve may fail for a `PlaceBuilder` when attempting to
     /// resolve a disjoint field whose root variable is not captured
@@ -281,11 +277,14 @@ impl<'tcx> PlaceBuilder<'tcx> {
     /// not captured. This can happen because the final mir that will be
     /// generated doesn't require a read for this place. Failures will only
     /// happen inside closures.
-    pub(in crate::build) fn try_upvars_resolved(
-        self,
+    pub(in crate::build) fn resolve_upvar(
+        &self,
         cx: &Builder<'_, 'tcx>,
-    ) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
-        to_upvars_resolved_place_builder(self, cx)
+    ) -> Option<PlaceBuilder<'tcx>> {
+        let PlaceBase::Upvar { var_hir_id, closure_def_id } = self.base else {
+            return None;
+        };
+        to_upvars_resolved_place_builder(cx, var_hir_id, closure_def_id, &self.projection)
     }
 
     pub(crate) fn base(&self) -> PlaceBase {
@@ -316,6 +315,14 @@ impl<'tcx> PlaceBuilder<'tcx> {
         self.projection.push(elem);
         self
     }
+
+    /// Same as `.clone().project(..)` but more efficient
+    pub(crate) fn clone_project(&self, elem: PlaceElem<'tcx>) -> Self {
+        Self {
+            base: self.base,
+            projection: Vec::from_iter(self.projection.iter().copied().chain([elem])),
+        }
+    }
 }
 
 impl<'tcx> From<Local> for PlaceBuilder<'tcx> {
@@ -355,7 +362,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         expr: &Expr<'tcx>,
     ) -> BlockAnd<Place<'tcx>> {
         let place_builder = unpack!(block = self.as_place_builder(block, expr));
-        block.and(place_builder.into_place(self))
+        block.and(place_builder.to_place(self))
     }
 
     /// This is used when constructing a compound `Place`, so that we can avoid creating
@@ -379,7 +386,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         expr: &Expr<'tcx>,
     ) -> BlockAnd<Place<'tcx>> {
         let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
-        block.and(place_builder.into_place(self))
+        block.and(place_builder.to_place(self))
     }
 
     /// This is used when constructing a compound `Place`, so that we can avoid creating
@@ -474,7 +481,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             inferred_ty: expr.ty,
                         });
 
-                    let place = place_builder.clone().into_place(this);
+                    let place = place_builder.to_place(this);
                     this.cfg.push(
                         block,
                         Statement {
@@ -599,7 +606,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let is_outermost_index = fake_borrow_temps.is_none();
         let fake_borrow_temps = fake_borrow_temps.unwrap_or(base_fake_borrow_temps);
 
-        let mut base_place =
+        let base_place =
             unpack!(block = self.expr_as_place(block, base, mutability, Some(fake_borrow_temps),));
 
         // Making this a *fresh* temporary means we do not have to worry about
@@ -607,14 +614,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // The "retagging" transformation (for Stacked Borrows) relies on this.
         let idx = unpack!(block = self.as_temp(block, temp_lifetime, index, Mutability::Not,));
 
-        block = self.bounds_check(block, base_place.clone(), idx, expr_span, source_info);
+        block = self.bounds_check(block, &base_place, idx, expr_span, source_info);
 
         if is_outermost_index {
             self.read_fake_borrows(block, fake_borrow_temps, source_info)
         } else {
-            base_place = base_place.expect_upvars_resolved(self);
             self.add_fake_borrows_of_base(
-                &base_place,
+                base_place.to_place(self),
                 block,
                 fake_borrow_temps,
                 expr_span,
@@ -628,7 +634,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     fn bounds_check(
         &mut self,
         block: BasicBlock,
-        slice: PlaceBuilder<'tcx>,
+        slice: &PlaceBuilder<'tcx>,
         index: Local,
         expr_span: Span,
         source_info: SourceInfo,
@@ -640,7 +646,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let lt = self.temp(bool_ty, expr_span);
 
         // len = len(slice)
-        self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice.into_place(self)));
+        self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice.to_place(self)));
         // lt = idx < len
         self.cfg.push_assign(
             block,
@@ -658,19 +664,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
     fn add_fake_borrows_of_base(
         &mut self,
-        base_place: &PlaceBuilder<'tcx>,
+        base_place: Place<'tcx>,
         block: BasicBlock,
         fake_borrow_temps: &mut Vec<Local>,
         expr_span: Span,
         source_info: SourceInfo,
     ) {
         let tcx = self.tcx;
-        let local = match base_place.base {
-            PlaceBase::Local(local) => local,
-            PlaceBase::Upvar { .. } => bug!("Expected PlacseBase::Local found Upvar"),
-        };
 
-        let place_ty = Place::ty_from(local, &base_place.projection, &self.local_decls, tcx);
+        let place_ty = base_place.ty(&self.local_decls, tcx);
         if let ty::Slice(_) = place_ty.ty.kind() {
             // We need to create fake borrows to ensure that the bounds
             // check that we just did stays valid. Since we can't assign to
@@ -680,7 +682,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 match elem {
                     ProjectionElem::Deref => {
                         let fake_borrow_deref_ty = Place::ty_from(
-                            local,
+                            base_place.local,
                             &base_place.projection[..idx],
                             &self.local_decls,
                             tcx,
@@ -698,14 +700,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             Rvalue::Ref(
                                 tcx.lifetimes.re_erased,
                                 BorrowKind::Shallow,
-                                Place { local, projection },
+                                Place { local: base_place.local, projection },
                             ),
                         );
                         fake_borrow_temps.push(fake_borrow_temp);
                     }
                     ProjectionElem::Index(_) => {
                         let index_ty = Place::ty_from(
-                            local,
+                            base_place.local,
                             &base_place.projection[..idx],
                             &self.local_decls,
                             tcx,
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 5c82fb1ddc0..0814793f277 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -369,8 +369,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     let place_builder =
                         unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
 
-                    if let Ok(place_builder_resolved) = place_builder.try_upvars_resolved(this) {
-                        let mir_place = place_builder_resolved.into_place(this);
+                    if let Some(mir_place) = place_builder.try_to_place(this) {
                         this.cfg.push_fake_read(
                             block,
                             this.source_info(this.tcx.hir().span(*hir_id)),
@@ -661,7 +660,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // by the parent itself. The mutability of the current capture
             // is same as that of the capture in the parent closure.
             PlaceBase::Upvar { .. } => {
-                let enclosing_upvars_resolved = arg_place_builder.clone().into_place(this);
+                let enclosing_upvars_resolved = arg_place_builder.to_place(this);
 
                 match enclosing_upvars_resolved.as_ref() {
                     PlaceRef {
@@ -698,7 +697,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
         };
 
-        let arg_place = arg_place_builder.into_place(this);
+        let arg_place = arg_place_builder.to_place(this);
 
         this.cfg.push_assign(
             block,
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index efb6eba7e57..218a26e6279 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -108,7 +108,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             ExprKind::Let { expr, ref pat } => {
                 let scope = this.local_scope();
                 let (true_block, false_block) = this.in_if_then_scope(scope, expr_span, |this| {
-                    this.lower_let_expr(block, &this.thir[expr], pat, scope, None, expr_span)
+                    this.lower_let_expr(block, &this.thir[expr], pat, scope, None, expr_span, true)
                 });
 
                 this.cfg.push_assign_constant(
@@ -358,10 +358,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         .map(|(n, ty)| match fields_map.get(&n) {
                             Some(v) => v.clone(),
                             None => {
-                                let place_builder = place_builder.clone();
-                                this.consume_by_copy_or_move(
-                                    place_builder.field(n, *ty).into_place(this),
-                                )
+                                let place = place_builder.clone_project(PlaceElem::Field(n, *ty));
+                                this.consume_by_copy_or_move(place.to_place(this))
                             }
                         })
                         .collect()
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index dfd8649cb97..691cbee2c73 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -84,6 +84,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 break_scope,
                 Some(variable_source_info.scope),
                 variable_source_info.span,
+                true,
             ),
             _ => {
                 let temp_scope = temp_scope_override.unwrap_or_else(|| this.local_scope());
@@ -168,7 +169,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let scrutinee_place =
             unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span,));
 
-        let mut arm_candidates = self.create_match_candidates(scrutinee_place.clone(), &arms);
+        let mut arm_candidates = self.create_match_candidates(&scrutinee_place, &arms);
 
         let match_has_guard = arm_candidates.iter().any(|(_, candidate)| candidate.has_guard);
         let mut candidates =
@@ -220,8 +221,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let cause_matched_place = FakeReadCause::ForMatchedPlace(None);
         let source_info = self.source_info(scrutinee_span);
 
-        if let Ok(scrutinee_builder) = scrutinee_place_builder.clone().try_upvars_resolved(self) {
-            let scrutinee_place = scrutinee_builder.into_place(self);
+        if let Some(scrutinee_place) = scrutinee_place_builder.try_to_place(self) {
             self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place);
         }
 
@@ -231,7 +231,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Create the initial `Candidate`s for a `match` expression.
     fn create_match_candidates<'pat>(
         &mut self,
-        scrutinee: PlaceBuilder<'tcx>,
+        scrutinee: &PlaceBuilder<'tcx>,
         arms: &'pat [ArmId],
     ) -> Vec<(&'pat Arm<'tcx>, Candidate<'pat, 'tcx>)>
     where
@@ -334,7 +334,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let arm_scope = (arm.scope, arm_source_info);
                 let match_scope = self.local_scope();
                 self.in_scope(arm_scope, arm.lint_level, |this| {
-                    // `try_upvars_resolved` may fail if it is unable to resolve the given
+                    // `try_to_place` may fail if it is unable to resolve the given
                     // `PlaceBuilder` inside a closure. In this case, we don't want to include
                     // a scrutinee place. `scrutinee_place_builder` will fail to be resolved
                     // if the only match arm is a wildcard (`_`).
@@ -345,19 +345,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     //    match foo { _ => () };
                     // };
                     // ```
-                    let mut opt_scrutinee_place: Option<(Option<&Place<'tcx>>, Span)> = None;
-                    let scrutinee_place: Place<'tcx>;
-                    if let Ok(scrutinee_builder) =
-                        scrutinee_place_builder.clone().try_upvars_resolved(this)
-                    {
-                        scrutinee_place = scrutinee_builder.into_place(this);
-                        opt_scrutinee_place = Some((Some(&scrutinee_place), scrutinee_span));
-                    }
+                    let scrutinee_place = scrutinee_place_builder.try_to_place(this);
+                    let opt_scrutinee_place =
+                        scrutinee_place.as_ref().map(|place| (Some(place), scrutinee_span));
                     let scope = this.declare_bindings(
                         None,
                         arm.span,
                         &arm.pattern,
-                        ArmHasGuard(arm.guard.is_some()),
+                        arm.guard.as_ref(),
                         opt_scrutinee_place,
                     );
 
@@ -591,7 +586,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             while let Some(next) = {
                 for binding in &candidate_ref.bindings {
                     let local = self.var_local_id(binding.var_id, OutsideGuard);
-                    // `try_upvars_resolved` may fail if it is unable to resolve the given
+                    // `try_to_place` may fail if it is unable to resolve the given
                     // `PlaceBuilder` inside a closure. In this case, we don't want to include
                     // a scrutinee place. `scrutinee_place_builder` will fail for destructured
                     // assignments. This is because a closure only captures the precise places
@@ -605,9 +600,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     //    let (v1, v2) = foo;
                     // };
                     // ```
-                    if let Ok(match_pair_resolved) = initializer.clone().try_upvars_resolved(self) {
-                        let place = match_pair_resolved.into_place(self);
-
+                    if let Some(place) = initializer.try_to_place(self) {
                         let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
                             VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
                         )))) = self.local_decls[local].local_info else {
@@ -645,7 +638,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         mut visibility_scope: Option<SourceScope>,
         scope_span: Span,
         pattern: &Pat<'tcx>,
-        has_guard: ArmHasGuard,
+        guard: Option<&Guard<'tcx>>,
         opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
     ) -> Option<SourceScope> {
         self.visit_primary_bindings(
@@ -667,12 +660,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     var,
                     ty,
                     user_ty,
-                    has_guard,
+                    ArmHasGuard(guard.is_some()),
                     opt_match_place.map(|(x, y)| (x.cloned(), y)),
                     pattern.span,
                 );
             },
         );
+        if let Some(Guard::IfLet(guard_pat, _)) = guard {
+            // FIXME: pass a proper `opt_match_place`
+            self.declare_bindings(visibility_scope, scope_span, guard_pat, None, None);
+        }
         visibility_scope
     }
 
@@ -1340,7 +1337,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 bug!("Or-patterns should have been sorted to the end");
             };
             let or_span = match_pair.pattern.span;
-            let place = match_pair.place;
 
             first_candidate.visit_leaves(|leaf_candidate| {
                 self.test_or_pattern(
@@ -1348,7 +1344,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     &mut otherwise,
                     pats,
                     or_span,
-                    place.clone(),
+                    &match_pair.place,
                     fake_borrows,
                 );
             });
@@ -1376,7 +1372,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         otherwise: &mut Option<BasicBlock>,
         pats: &'pat [Box<Pat<'tcx>>],
         or_span: Span,
-        place: PlaceBuilder<'tcx>,
+        place: &PlaceBuilder<'tcx>,
         fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
     ) {
         debug!("candidate={:#?}\npats={:#?}", candidate, pats);
@@ -1594,10 +1590,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
 
         // Insert a Shallow borrow of any places that is switched on.
-        if let Some(fb) = fake_borrows && let Ok(match_place_resolved) =
-            match_place.clone().try_upvars_resolved(self)
+        if let Some(fb) = fake_borrows
+            && let Some(resolved_place) = match_place.try_to_place(self)
         {
-            let resolved_place = match_place_resolved.into_place(self);
             fb.insert(resolved_place);
         }
 
@@ -1616,7 +1611,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // encounter a candidate where the test is not relevant; at
         // that point, we stop sorting.
         while let Some(candidate) = candidates.first_mut() {
-            let Some(idx) = self.sort_candidate(&match_place.clone(), &test, candidate) else {
+            let Some(idx) = self.sort_candidate(&match_place, &test, candidate) else {
                 break;
             };
             let (candidate, rest) = candidates.split_first_mut().unwrap();
@@ -1685,7 +1680,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             target_blocks
         };
 
-        self.perform_test(span, scrutinee_span, block, match_place, &test, make_target_blocks);
+        self.perform_test(span, scrutinee_span, block, &match_place, &test, make_target_blocks);
     }
 
     /// Determine the fake borrows that are needed from a set of places that
@@ -1766,6 +1761,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 // Pat binding - used for `let` and function parameters as well.
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
+    /// If the bindings have already been declared, set `declare_bindings` to
+    /// `false` to avoid duplicated bindings declaration. Used for if-let guards.
     pub(crate) fn lower_let_expr(
         &mut self,
         mut block: BasicBlock,
@@ -1774,6 +1771,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         else_target: region::Scope,
         source_scope: Option<SourceScope>,
         span: Span,
+        declare_bindings: bool,
     ) -> BlockAnd<()> {
         let expr_span = expr.span;
         let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span));
@@ -1788,22 +1786,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             false,
             &mut [&mut guard_candidate, &mut otherwise_candidate],
         );
-        let mut opt_expr_place: Option<(Option<&Place<'tcx>>, Span)> = None;
-        let expr_place: Place<'tcx>;
-        if let Ok(expr_builder) = expr_place_builder.try_upvars_resolved(self) {
-            expr_place = expr_builder.into_place(self);
-            opt_expr_place = Some((Some(&expr_place), expr_span));
-        }
+        let expr_place = expr_place_builder.try_to_place(self);
+        let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span));
         let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap();
         self.break_for_else(otherwise_post_guard_block, else_target, self.source_info(expr_span));
 
-        self.declare_bindings(
-            source_scope,
-            pat.span.to(span),
-            pat,
-            ArmHasGuard(false),
-            opt_expr_place,
-        );
+        if declare_bindings {
+            self.declare_bindings(source_scope, pat.span.to(span), pat, None, opt_expr_place);
+        }
 
         let post_guard_block = self.bind_pattern(
             self.source_info(pat.span),
@@ -1984,7 +1974,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     Guard::IfLet(ref pat, scrutinee) => {
                         let s = &this.thir[scrutinee];
                         guard_span = s.span;
-                        this.lower_let_expr(block, s, pat, match_scope, None, arm.span)
+                        this.lower_let_expr(block, s, pat, match_scope, None, arm.span, false)
                     }
                 });
 
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index caf27eb39d7..f6b1955fdec 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -73,8 +73,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             {
                 existing_bindings.extend_from_slice(&new_bindings);
                 mem::swap(&mut candidate.bindings, &mut existing_bindings);
-                candidate.subcandidates =
-                    self.create_or_subcandidates(candidate, place.clone(), pats);
+                candidate.subcandidates = self.create_or_subcandidates(candidate, &place, pats);
                 return true;
             }
 
@@ -127,7 +126,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     fn create_or_subcandidates<'pat>(
         &mut self,
         candidate: &Candidate<'pat, 'tcx>,
-        place: PlaceBuilder<'tcx>,
+        place: &PlaceBuilder<'tcx>,
         pats: &'pat [Box<Pat<'tcx>>],
     ) -> Vec<Candidate<'pat, 'tcx>> {
         pats.iter()
@@ -156,10 +155,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 ascription: thir::Ascription { ref annotation, variance },
             } => {
                 // Apply the type ascription to the value at `match_pair.place`, which is the
-                if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) {
+                if let Some(source) = match_pair.place.try_to_place(self) {
                     candidate.ascriptions.push(Ascription {
                         annotation: annotation.clone(),
-                        source: place_resolved.into_place(self),
+                        source,
                         variance,
                     });
                 }
@@ -183,10 +182,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 ref subpattern,
                 is_primary: _,
             } => {
-                if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) {
+                if let Some(source) = match_pair.place.try_to_place(self) {
                     candidate.bindings.push(Binding {
                         span: match_pair.pattern.span,
-                        source: place_resolved.into_place(self),
+                        source,
                         var_id: var,
                         binding_mode: mode,
                     });
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index a62cfecf78b..58513bde2aa 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -150,11 +150,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         match_start_span: Span,
         scrutinee_span: Span,
         block: BasicBlock,
-        place_builder: PlaceBuilder<'tcx>,
+        place_builder: &PlaceBuilder<'tcx>,
         test: &Test<'tcx>,
         make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>,
     ) {
-        let place = place_builder.into_place(self);
+        let place = place_builder.to_place(self);
         let place_ty = place.ty(&self.local_decls, self.tcx);
         debug!(?place, ?place_ty,);
 
@@ -760,7 +760,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let downcast_place = match_pair.place.downcast(adt_def, variant_index); // `(x as Variant)`
         let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
             // e.g., `(x as Variant).0`
-            let place = downcast_place.clone().field(subpattern.field, subpattern.pattern.ty);
+            let place = downcast_place
+                .clone_project(PlaceElem::Field(subpattern.field, subpattern.pattern.ty));
             // e.g., `(x as Variant).0 @ P1`
             MatchPair::new(place, &subpattern.pattern, self)
         });
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index b854ba47f8f..bd435f9ab00 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -18,7 +18,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         subpatterns
             .iter()
             .map(|fieldpat| {
-                let place = place.clone().field(fieldpat.field, fieldpat.pattern.ty);
+                let place =
+                    place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty));
                 MatchPair::new(place, &fieldpat.pattern, self)
             })
             .collect()
@@ -33,26 +34,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         suffix: &'pat [Box<Pat<'tcx>>],
     ) {
         let tcx = self.tcx;
-        let (min_length, exact_size) =
-            if let Ok(place_resolved) = place.clone().try_upvars_resolved(self) {
-                match place_resolved.into_place(self).ty(&self.local_decls, tcx).ty.kind() {
-                    ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
-                    _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
-                }
-            } else {
-                ((prefix.len() + suffix.len()).try_into().unwrap(), false)
-            };
+        let (min_length, exact_size) = if let Some(place_resolved) = place.try_to_place(self) {
+            match place_resolved.ty(&self.local_decls, tcx).ty.kind() {
+                ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
+                _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
+            }
+        } else {
+            ((prefix.len() + suffix.len()).try_into().unwrap(), false)
+        };
 
         match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| {
             let elem =
                 ProjectionElem::ConstantIndex { offset: idx as u64, min_length, from_end: false };
-            let place = place.clone().project(elem);
-            MatchPair::new(place, subpattern, self)
+            MatchPair::new(place.clone_project(elem), subpattern, self)
         }));
 
         if let Some(subslice_pat) = opt_slice {
             let suffix_len = suffix.len() as u64;
-            let subslice = place.clone().project(ProjectionElem::Subslice {
+            let subslice = place.clone_project(PlaceElem::Subslice {
                 from: prefix.len() as u64,
                 to: if exact_size { min_length - suffix_len } else { suffix_len },
                 from_end: !exact_size,
@@ -67,7 +66,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 min_length,
                 from_end: !exact_size,
             };
-            let place = place.clone().project(elem);
+            let place = place.clone_project(elem);
             MatchPair::new(place, subpattern, self)
         }));
     }
@@ -97,15 +96,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
 impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
     pub(in crate::build) fn new(
-        place: PlaceBuilder<'tcx>,
+        mut place: PlaceBuilder<'tcx>,
         pattern: &'pat Pat<'tcx>,
         cx: &Builder<'_, 'tcx>,
     ) -> MatchPair<'pat, 'tcx> {
         // Force the place type to the pattern's type.
         // FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
-        let mut place = match place.try_upvars_resolved(cx) {
-            Ok(val) | Err(val) => val,
-        };
+        if let Some(resolved) = place.resolve_upvar(cx) {
+            place = resolved;
+        }
 
         // Only add the OpaqueCast projection if the given place is an opaque type and the
         // expected type from the pattern is not.
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 437ac8d82a1..0b76122913e 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -924,7 +924,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         scope,
                         expr.span,
                         &pat,
-                        matches::ArmHasGuard(false),
+                        None,
                         Some((Some(&place), span)),
                     );
                     let place_builder = PlaceBuilder::from(local);
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 60e64b45963..5fa41ebeb6e 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -486,7 +486,7 @@ impl<'tcx> Cx<'tcx> {
                             substs,
                             user_ty,
                             fields: self.field_refs(fields),
-                            base: base.as_ref().map(|base| FruInfo {
+                            base: base.map(|base| FruInfo {
                                 base: self.mirror_expr(base),
                                 field_types: self.typeck_results().fru_field_types()[expr.hir_id]
                                     .iter()
@@ -589,7 +589,7 @@ impl<'tcx> Cx<'tcx> {
                             InlineAsmOperand::Out {
                                 reg,
                                 late,
-                                expr: expr.as_ref().map(|expr| self.mirror_expr(expr)),
+                                expr: expr.map(|expr| self.mirror_expr(expr)),
                             }
                         }
                         hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
@@ -604,7 +604,7 @@ impl<'tcx> Cx<'tcx> {
                             reg,
                             late,
                             in_expr: self.mirror_expr(in_expr),
-                            out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)),
+                            out_expr: out_expr.map(|expr| self.mirror_expr(expr)),
                         },
                         hir::InlineAsmOperand::Const { ref anon_const } => {
                             let value = mir::ConstantKind::from_anon_const(
@@ -656,13 +656,11 @@ impl<'tcx> Cx<'tcx> {
 
                 ExprKind::Repeat { value: self.mirror_expr(v), count: *count }
             }
-            hir::ExprKind::Ret(ref v) => {
-                ExprKind::Return { value: v.as_ref().map(|v| self.mirror_expr(v)) }
-            }
+            hir::ExprKind::Ret(ref v) => ExprKind::Return { value: v.map(|v| self.mirror_expr(v)) },
             hir::ExprKind::Break(dest, ref value) => match dest.target_id {
                 Ok(target_id) => ExprKind::Break {
                     label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node },
-                    value: value.as_ref().map(|value| self.mirror_expr(value)),
+                    value: value.map(|value| self.mirror_expr(value)),
                 },
                 Err(err) => bug!("invalid loop id for break: {}", err),
             },
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 0df228a0d59..e369dba5524 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -564,7 +564,7 @@ fn check_for_bindings_named_same_as_variants(
             && let ty::Adt(edef, _) = pat_ty.kind()
             && edef.is_enum()
             && edef.variants().iter().any(|variant| {
-                variant.ident(cx.tcx) == ident && variant.ctor_kind == CtorKind::Const
+                variant.ident(cx.tcx) == ident && variant.ctor_kind() == Some(CtorKind::Const)
             })
         {
             let variant_count = edef.variants().len();
@@ -1044,11 +1044,19 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa
                     name,
                     typeck_results.node_type(pat.hir_id),
                 );
-                sess.struct_span_err(pat.span, "borrow of moved value")
-                    .span_label(binding_span, format!("value moved into `{}` here", name))
+                let mut err = sess.struct_span_err(pat.span, "borrow of moved value");
+                err.span_label(binding_span, format!("value moved into `{}` here", name))
                     .span_label(binding_span, occurs_because)
-                    .span_labels(conflicts_ref, "value borrowed here after move")
-                    .emit();
+                    .span_labels(conflicts_ref, "value borrowed here after move");
+                if pat.span.contains(binding_span) {
+                    err.span_suggestion_verbose(
+                        binding_span.shrink_to_lo(),
+                        "borrow this binding in the pattern to avoid moving the value",
+                        "ref ".to_string(),
+                        Applicability::MachineApplicable,
+                    );
+                }
+                err.emit();
             }
             return;
         }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 4b6608faba6..4c2a80e523f 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -216,7 +216,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 let lo = lo_expr.map(|e| self.lower_range_expr(e));
                 let hi = hi_expr.map(|e| self.lower_range_expr(e));
 
-                let (lp, hp) = (lo.as_ref().map(|x| &x.0), hi.as_ref().map(|x| &x.0));
+                let (lp, hp) = (lo.as_ref().map(|(x, _)| x), hi.as_ref().map(|(x, _)| x));
                 let mut kind = match self.normalize_range_pattern_ends(ty, lp, hp) {
                     Some((lc, hc)) => self.lower_pattern_range(ty, lc, hc, end, lo_span),
                     None => {
@@ -358,7 +358,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         &mut self,
         pat: &'tcx Option<&'tcx hir::Pat<'tcx>>,
     ) -> Option<Box<Pat<'tcx>>> {
-        pat.as_ref().map(|p| self.lower_pattern(p))
+        pat.map(|p| self.lower_pattern(p))
     }
 
     fn slice_or_array_pattern(
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index fcd63b6cfa1..ffe4d43bc88 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -11,10 +11,10 @@
 //! generator in the MIR, since it is used to create the drop glue for the generator. We'd get
 //! infinite recursion otherwise.
 //!
-//! This pass creates the implementation for the Generator::resume function and the drop shim
-//! for the generator based on the MIR input. It converts the generator argument from Self to
-//! &mut Self adding derefs in the MIR as needed. It computes the final layout of the generator
-//! struct which looks like this:
+//! This pass creates the implementation for either the `Generator::resume` or `Future::poll`
+//! function and the drop shim for the generator based on the MIR input.
+//! It converts the generator argument from Self to &mut Self adding derefs in the MIR as needed.
+//! It computes the final layout of the generator struct which looks like this:
 //!     First upvars are stored
 //!     It is followed by the generator state field.
 //!     Then finally the MIR locals which are live across a suspension point are stored.
@@ -32,14 +32,15 @@
 //!     2 - Generator has been poisoned
 //!
 //! It also rewrites `return x` and `yield y` as setting a new generator state and returning
-//! GeneratorState::Complete(x) and GeneratorState::Yielded(y) respectively.
+//! `GeneratorState::Complete(x)` and `GeneratorState::Yielded(y)`,
+//! or `Poll::Ready(x)` and `Poll::Pending` respectively.
 //! MIR locals which are live across a suspension point are moved to the generator struct
 //! with references to them being updated with references to the generator struct.
 //!
 //! The pass creates two functions which have a switch on the generator state giving
 //! the action to take.
 //!
-//! One of them is the implementation of Generator::resume.
+//! One of them is the implementation of `Generator::resume` / `Future::poll`.
 //! For generators with state 0 (unresumed) it starts the execution of the generator.
 //! For generators with state 1 (returned) and state 2 (poisoned) it panics.
 //! Otherwise it continues the execution from the last suspension point.
@@ -56,6 +57,7 @@ use crate::MirPass;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
+use rustc_hir::GeneratorKind;
 use rustc_index::bit_set::{BitMatrix, BitSet, GrowableBitSet};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::dump_mir;
@@ -215,6 +217,7 @@ struct SuspensionPoint<'tcx> {
 
 struct TransformVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
+    is_async_kind: bool,
     state_adt_ref: AdtDef<'tcx>,
     state_substs: SubstsRef<'tcx>,
 
@@ -239,28 +242,57 @@ struct TransformVisitor<'tcx> {
 }
 
 impl<'tcx> TransformVisitor<'tcx> {
-    // Make a GeneratorState variant assignment. `core::ops::GeneratorState` only has single
-    // element tuple variants, so we can just write to the downcasted first field and then set the
+    // Make a `GeneratorState` or `Poll` variant assignment.
+    //
+    // `core::ops::GeneratorState` only has single element tuple variants,
+    // so we can just write to the downcasted first field and then set the
     // discriminant to the appropriate variant.
     fn make_state(
         &self,
-        idx: VariantIdx,
         val: Operand<'tcx>,
         source_info: SourceInfo,
-    ) -> impl Iterator<Item = Statement<'tcx>> {
+        is_return: bool,
+        statements: &mut Vec<Statement<'tcx>>,
+    ) {
+        let idx = VariantIdx::new(match (is_return, self.is_async_kind) {
+            (true, false) => 1,  // GeneratorState::Complete
+            (false, false) => 0, // GeneratorState::Yielded
+            (true, true) => 0,   // Poll::Ready
+            (false, true) => 1,  // Poll::Pending
+        });
+
         let kind = AggregateKind::Adt(self.state_adt_ref.did(), idx, self.state_substs, None, None);
+
+        // `Poll::Pending`
+        if self.is_async_kind && idx == VariantIdx::new(1) {
+            assert_eq!(self.state_adt_ref.variant(idx).fields.len(), 0);
+
+            // FIXME(swatinem): assert that `val` is indeed unit?
+            statements.extend(expand_aggregate(
+                Place::return_place(),
+                std::iter::empty(),
+                kind,
+                source_info,
+                self.tcx,
+            ));
+            return;
+        }
+
+        // else: `Poll::Ready(x)`, `GeneratorState::Yielded(x)` or `GeneratorState::Complete(x)`
         assert_eq!(self.state_adt_ref.variant(idx).fields.len(), 1);
+
         let ty = self
             .tcx
             .bound_type_of(self.state_adt_ref.variant(idx).fields[0].did)
             .subst(self.tcx, self.state_substs);
-        expand_aggregate(
+
+        statements.extend(expand_aggregate(
             Place::return_place(),
             std::iter::once((val, ty)),
             kind,
             source_info,
             self.tcx,
-        )
+        ));
     }
 
     // Create a Place referencing a generator struct field
@@ -331,22 +363,19 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
         });
 
         let ret_val = match data.terminator().kind {
-            TerminatorKind::Return => Some((
-                VariantIdx::new(1),
-                None,
-                Operand::Move(Place::from(self.new_ret_local)),
-                None,
-            )),
+            TerminatorKind::Return => {
+                Some((true, None, Operand::Move(Place::from(self.new_ret_local)), None))
+            }
             TerminatorKind::Yield { ref value, resume, resume_arg, drop } => {
-                Some((VariantIdx::new(0), Some((resume, resume_arg)), value.clone(), drop))
+                Some((false, Some((resume, resume_arg)), value.clone(), drop))
             }
             _ => None,
         };
 
-        if let Some((state_idx, resume, v, drop)) = ret_val {
+        if let Some((is_return, resume, v, drop)) = ret_val {
             let source_info = data.terminator().source_info;
             // We must assign the value first in case it gets declared dead below
-            data.statements.extend(self.make_state(state_idx, v, source_info));
+            self.make_state(v, source_info, is_return, &mut data.statements);
             let state = if let Some((resume, mut resume_arg)) = resume {
                 // Yield
                 let state = RESERVED_VARIANTS + self.suspension_points.len();
@@ -1268,10 +1297,20 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
             }
         };
 
-        // Compute GeneratorState<yield_ty, return_ty>
-        let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
-        let state_adt_ref = tcx.adt_def(state_did);
-        let state_substs = tcx.intern_substs(&[yield_ty.into(), body.return_ty().into()]);
+        let is_async_kind = body.generator_kind().unwrap() != GeneratorKind::Gen;
+        let (state_adt_ref, state_substs) = if is_async_kind {
+            // Compute Poll<return_ty>
+            let state_did = tcx.require_lang_item(LangItem::Poll, None);
+            let state_adt_ref = tcx.adt_def(state_did);
+            let state_substs = tcx.intern_substs(&[body.return_ty().into()]);
+            (state_adt_ref, state_substs)
+        } else {
+            // Compute GeneratorState<yield_ty, return_ty>
+            let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
+            let state_adt_ref = tcx.adt_def(state_did);
+            let state_substs = tcx.intern_substs(&[yield_ty.into(), body.return_ty().into()]);
+            (state_adt_ref, state_substs)
+        };
         let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
 
         // We rename RETURN_PLACE which has type mir.return_ty to new_ret_local
@@ -1327,9 +1366,11 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
         // Run the transformation which converts Places from Local to generator struct
         // accesses for locals in `remap`.
         // It also rewrites `return x` and `yield y` as writing a new generator state and returning
-        // GeneratorState::Complete(x) and GeneratorState::Yielded(y) respectively.
+        // either GeneratorState::Complete(x) and GeneratorState::Yielded(y),
+        // or Poll::Ready(x) and Poll::Pending respectively depending on `is_async_kind`.
         let mut transform = TransformVisitor {
             tcx,
+            is_async_kind,
             state_adt_ref,
             state_substs,
             remap,
@@ -1367,7 +1408,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
 
         body.generator.as_mut().unwrap().generator_drop = Some(drop_shim);
 
-        // Create the Generator::resume function
+        // Create the Generator::resume / Future::poll function
         create_generator_resume_function(tcx, transform, body, can_return);
 
         // Run derefer to fix Derefs that are not in the first place
diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
index 96ea15f1b80..be0aa0fc4c1 100644
--- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
@@ -65,7 +65,7 @@ fn variant_discriminants<'tcx>(
         Variants::Multiple { variants, .. } => variants
             .iter_enumerated()
             .filter_map(|(idx, layout)| {
-                (layout.abi() != Abi::Uninhabited)
+                (layout.abi != Abi::Uninhabited)
                     .then(|| ty.discriminant_for_variant(tcx, idx).unwrap().val)
             })
             .collect(),
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index fb2cee9e346..0ed24fe849c 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -245,9 +245,9 @@ impl<'a> Parser<'a> {
     ///     PATH `=` UNSUFFIXED_LIT
     /// The delimiters or `=` are still put into the resulting token stream.
     pub fn parse_attr_item(&mut self, capture_tokens: bool) -> PResult<'a, ast::AttrItem> {
-        let item = match self.token.kind {
-            token::Interpolated(ref nt) => match **nt {
-                Nonterminal::NtMeta(ref item) => Some(item.clone().into_inner()),
+        let item = match &self.token.kind {
+            token::Interpolated(nt) => match &**nt {
+                Nonterminal::NtMeta(item) => Some(item.clone().into_inner()),
                 _ => None,
             },
             _ => None,
@@ -364,9 +364,9 @@ impl<'a> Parser<'a> {
     /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
     /// ```
     pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
-        let nt_meta = match self.token.kind {
-            token::Interpolated(ref nt) => match **nt {
-                token::NtMeta(ref e) => Some(e.clone()),
+        let nt_meta = match &self.token.kind {
+            token::Interpolated(nt) => match &**nt {
+                token::NtMeta(e) => Some(e.clone()),
                 _ => None,
             },
             _ => None,
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 4c626539238..3f5baf343c9 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -973,7 +973,7 @@ impl<'a> Parser<'a> {
         inner_op: &Expr,
         outer_op: &Spanned<AssocOp>,
     ) -> bool /* advanced the cursor */ {
-        if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind {
+        if let ExprKind::Binary(op, l1, r1) = &inner_op.kind {
             if let ExprKind::Field(_, ident) = l1.kind
                 && ident.as_str().parse::<i32>().is_err()
                 && !matches!(r1.kind, ExprKind::Lit(_))
@@ -1079,8 +1079,8 @@ impl<'a> Parser<'a> {
 
         let mk_err_expr = |this: &Self, span| Ok(Some(this.mk_expr(span, ExprKind::Err)));
 
-        match inner_op.kind {
-            ExprKind::Binary(op, ref l1, ref r1) if op.node.is_comparison() => {
+        match &inner_op.kind {
+            ExprKind::Binary(op, l1, r1) if op.node.is_comparison() => {
                 let mut err = ComparisonOperatorsCannotBeChained {
                     span: vec![op.span, self.prev_token.span],
                     suggest_turbofish: None,
@@ -1237,8 +1237,8 @@ impl<'a> Parser<'a> {
         let bounds = self.parse_generic_bounds(None)?;
         let sum_span = ty.span.to(self.prev_token.span);
 
-        let sub = match ty.kind {
-            TyKind::Rptr(ref lifetime, ref mut_ty) => {
+        let sub = match &ty.kind {
+            TyKind::Rptr(lifetime, mut_ty) => {
                 let sum_with_parens = pprust::to_string(|s| {
                     s.s.word("&");
                     s.print_opt_lifetime(lifetime);
@@ -2565,7 +2565,7 @@ impl<'a> Parser<'a> {
             if let [a, b] = segments {
                 let (a_span, b_span) = (a.span(), b.span());
                 let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo());
-                if self.span_to_snippet(between_span).as_ref().map(|a| &a[..]) == Ok(":: ") {
+                if self.span_to_snippet(between_span).as_deref() == Ok(":: ") {
                     return Err(DoubleColonInBound {
                         span: path.span.shrink_to_hi(),
                         between: between_span,
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index ba73fbd3e12..9f2267efb82 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -414,7 +414,7 @@ impl<'a> Parser<'a> {
                 self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
                 false
             }
-            (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => false,
+            (true, Some(op)) if !op.can_continue_expr_unambiguously() => false,
             (true, Some(_)) => {
                 self.error_found_expr_would_be_stmt(lhs);
                 true
@@ -1728,13 +1728,13 @@ impl<'a> Parser<'a> {
             || !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
         {
             let expr = self.parse_expr_opt()?;
-            if let Some(ref expr) = expr {
+            if let Some(expr) = &expr {
                 if label.is_some()
                     && matches!(
                         expr.kind,
                         ExprKind::While(_, _, None)
                             | ExprKind::ForLoop(_, _, _, None)
-                            | ExprKind::Loop(_, None)
+                            | ExprKind::Loop(_, None, _)
                             | ExprKind::Block(_, None)
                     )
                 {
@@ -2444,10 +2444,11 @@ impl<'a> Parser<'a> {
 
     /// Parses `loop { ... }` (`loop` token already eaten).
     fn parse_loop_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
+        let loop_span = self.prev_token.span;
         let (attrs, body) = self.parse_inner_attrs_and_block()?;
         Ok(self.mk_expr_with_attrs(
             lo.to(self.prev_token.span),
-            ExprKind::Loop(body, opt_label),
+            ExprKind::Loop(body, opt_label, loop_span),
             attrs,
         ))
     }
@@ -2590,8 +2591,8 @@ impl<'a> Parser<'a> {
         // Used to check the `let_chains` and `if_let_guard` features mostly by scanning
         // `&&` tokens.
         fn check_let_expr(expr: &Expr) -> (bool, bool) {
-            match expr.kind {
-                ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, ref lhs, ref rhs) => {
+            match &expr.kind {
+                ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, lhs, rhs) => {
                     let lhs_rslt = check_let_expr(lhs);
                     let rhs_rslt = check_let_expr(rhs);
                     (lhs_rslt.0 || rhs_rslt.0, false)
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 20b01f554f2..767fb9378be 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -222,7 +222,8 @@ impl<'a> Parser<'a> {
             self.parse_use_item()?
         } else if self.check_fn_front_matter(def_final, case) {
             // FUNCTION ITEM
-            let (ident, sig, generics, body) = self.parse_fn(attrs, fn_parse_mode, lo, vis)?;
+            let (ident, sig, generics, body) =
+                self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
             (ident, ItemKind::Fn(Box::new(Fn { defaultness: def_(), sig, generics, body })))
         } else if self.eat_keyword(kw::Extern) {
             if self.eat_keyword(kw::Crate) {
@@ -1255,8 +1256,8 @@ impl<'a> Parser<'a> {
             }
         };
 
-        match impl_info.1 {
-            ItemKind::Impl(box Impl { of_trait: Some(ref trai), ref mut constness, .. }) => {
+        match &mut impl_info.1 {
+            ItemKind::Impl(box Impl { of_trait: Some(trai), constness, .. }) => {
                 *constness = Const::Yes(const_span);
 
                 let before_trait = trai.path.span.shrink_to_lo();
@@ -1793,7 +1794,13 @@ impl<'a> Parser<'a> {
                 };
                 // We use `parse_fn` to get a span for the function
                 let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
-                match self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis) {
+                match self.parse_fn(
+                    &mut AttrVec::new(),
+                    fn_parse_mode,
+                    lo,
+                    &inherited_vis,
+                    Case::Insensitive,
+                ) {
                     Ok(_) => {
                         let mut err = self.struct_span_err(
                             lo.to(self.prev_token.span),
@@ -2114,8 +2121,9 @@ impl<'a> Parser<'a> {
         fn_parse_mode: FnParseMode,
         sig_lo: Span,
         vis: &Visibility,
+        case: Case,
     ) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
-        let header = self.parse_fn_front_matter(vis)?; // `const ... fn`
+        let header = self.parse_fn_front_matter(vis, case)?; // `const ... fn`
         let ident = self.parse_ident()?; // `foo`
         let mut generics = self.parse_generics()?; // `<'a, T, ...>`
         let decl =
@@ -2239,24 +2247,28 @@ impl<'a> Parser<'a> {
     ///
     /// `vis` represents the visibility that was already parsed, if any. Use
     /// `Visibility::Inherited` when no visibility is known.
-    pub(super) fn parse_fn_front_matter(&mut self, orig_vis: &Visibility) -> PResult<'a, FnHeader> {
+    pub(super) fn parse_fn_front_matter(
+        &mut self,
+        orig_vis: &Visibility,
+        case: Case,
+    ) -> PResult<'a, FnHeader> {
         let sp_start = self.token.span;
-        let constness = self.parse_constness(Case::Insensitive);
+        let constness = self.parse_constness(case);
 
         let async_start_sp = self.token.span;
-        let asyncness = self.parse_asyncness(Case::Insensitive);
+        let asyncness = self.parse_asyncness(case);
 
         let unsafe_start_sp = self.token.span;
-        let unsafety = self.parse_unsafety(Case::Insensitive);
+        let unsafety = self.parse_unsafety(case);
 
         let ext_start_sp = self.token.span;
-        let ext = self.parse_extern(Case::Insensitive);
+        let ext = self.parse_extern(case);
 
         if let Async::Yes { span, .. } = asyncness {
             self.ban_async_in_2015(span);
         }
 
-        if !self.eat_keyword_case(kw::Fn, Case::Insensitive) {
+        if !self.eat_keyword_case(kw::Fn, case) {
             // It is possible for `expect_one_of` to recover given the contents of
             // `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't
             // account for this.
@@ -2585,8 +2597,8 @@ impl<'a> Parser<'a> {
     }
 
     fn is_named_param(&self) -> bool {
-        let offset = match self.token.kind {
-            token::Interpolated(ref nt) => match **nt {
+        let offset = match &self.token.kind {
+            token::Interpolated(nt) => match **nt {
                 token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
                 _ => 0,
             },
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 8878c404c58..4d8bff28b05 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -384,8 +384,8 @@ enum TokenType {
 
 impl TokenType {
     fn to_string(&self) -> String {
-        match *self {
-            TokenType::Token(ref t) => format!("`{}`", pprust::token_kind_to_string(t)),
+        match self {
+            TokenType::Token(t) => format!("`{}`", pprust::token_kind_to_string(t)),
             TokenType::Keyword(kw) => format!("`{}`", kw),
             TokenType::Operator => "an operator".to_string(),
             TokenType::Lifetime => "lifetime".to_string(),
@@ -738,8 +738,8 @@ impl<'a> Parser<'a> {
 
     fn check_inline_const(&self, dist: usize) -> bool {
         self.is_keyword_ahead(dist, &[kw::Const])
-            && self.look_ahead(dist + 1, |t| match t.kind {
-                token::Interpolated(ref nt) => matches!(**nt, token::NtBlock(..)),
+            && self.look_ahead(dist + 1, |t| match &t.kind {
+                token::Interpolated(nt) => matches!(**nt, token::NtBlock(..)),
                 token::OpenDelim(Delimiter::Brace) => true,
                 _ => false,
             })
@@ -860,7 +860,7 @@ impl<'a> Parser<'a> {
             if let token::CloseDelim(..) | token::Eof = self.token.kind {
                 break;
             }
-            if let Some(ref t) = sep.sep {
+            if let Some(t) = &sep.sep {
                 if first {
                     first = false;
                 } else {
@@ -895,7 +895,7 @@ impl<'a> Parser<'a> {
 
                                 _ => {
                                     // Attempt to keep parsing if it was a similar separator.
-                                    if let Some(ref tokens) = t.similar_tokens() {
+                                    if let Some(tokens) = t.similar_tokens() {
                                         if tokens.contains(&self.token.kind) && !unclosed_delims {
                                             self.bump();
                                         }
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 103dd801257..239ed79ce2f 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -42,9 +42,9 @@ impl<'a> Parser<'a> {
                 token::Comma | token::Ident(..) | token::Interpolated(..) => true,
                 _ => token.can_begin_type(),
             },
-            NonterminalKind::Block => match token.kind {
+            NonterminalKind::Block => match &token.kind {
                 token::OpenDelim(Delimiter::Brace) => true,
-                token::Interpolated(ref nt) => !matches!(
+                token::Interpolated(nt) => !matches!(
                     **nt,
                     token::NtItem(_)
                         | token::NtPat(_)
@@ -56,16 +56,16 @@ impl<'a> Parser<'a> {
                 ),
                 _ => false,
             },
-            NonterminalKind::Path | NonterminalKind::Meta => match token.kind {
+            NonterminalKind::Path | NonterminalKind::Meta => match &token.kind {
                 token::ModSep | token::Ident(..) => true,
-                token::Interpolated(ref nt) => match **nt {
+                token::Interpolated(nt) => match **nt {
                     token::NtPath(_) | token::NtMeta(_) => true,
                     _ => may_be_ident(&nt),
                 },
                 _ => false,
             },
             NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
-                match token.kind {
+                match &token.kind {
                 token::Ident(..) |                          // box, ref, mut, and other identifiers (can stricten)
                 token::OpenDelim(Delimiter::Parenthesis) |  // tuple pattern
                 token::OpenDelim(Delimiter::Bracket) |      // slice pattern
@@ -80,13 +80,13 @@ impl<'a> Parser<'a> {
                 token::BinOp(token::Shl) => true,           // path (double UFCS)
                 // leading vert `|` or-pattern
                 token::BinOp(token::Or) =>  matches!(kind, NonterminalKind::PatWithOr {..}),
-                token::Interpolated(ref nt) => may_be_ident(nt),
+                token::Interpolated(nt) => may_be_ident(nt),
                 _ => false,
             }
             }
-            NonterminalKind::Lifetime => match token.kind {
+            NonterminalKind::Lifetime => match &token.kind {
                 token::Lifetime(_) => true,
-                token::Interpolated(ref nt) => {
+                token::Interpolated(nt) => {
                     matches!(**nt, token::NtLifetime(_))
                 }
                 _ => false,
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index bf52febb107..cbeec951e2d 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -485,7 +485,7 @@ impl<'a> Parser<'a> {
         let mut rhs = self.parse_pat_no_top_alt(None)?;
         let sp = lhs.span.to(rhs.span);
 
-        if let PatKind::Ident(_, _, ref mut sub @ None) = rhs.kind {
+        if let PatKind::Ident(_, _, sub @ None) = &mut rhs.kind {
             // The user inverted the order, so help them fix that.
             let mut applicability = Applicability::MachineApplicable;
             // FIXME(bindings_after_at): Remove this code when stabilizing the feature.
@@ -595,7 +595,7 @@ impl<'a> Parser<'a> {
         self.recover_additional_muts();
 
         // Make sure we don't allow e.g. `let mut $p;` where `$p:pat`.
-        if let token::Interpolated(ref nt) = self.token.kind {
+        if let token::Interpolated(nt) = &self.token.kind {
             if let token::NtPat(_) = **nt {
                 self.expected_ident_found().emit();
             }
@@ -796,7 +796,7 @@ impl<'a> Parser<'a> {
     /// expression syntax `...expr` for splatting in expressions.
     fn parse_pat_range_to(&mut self, mut re: Spanned<RangeEnd>) -> PResult<'a, PatKind> {
         let end = self.parse_pat_range_end()?;
-        if let RangeEnd::Included(ref mut syn @ RangeSyntax::DotDotDot) = &mut re.node {
+        if let RangeEnd::Included(syn @ RangeSyntax::DotDotDot) = &mut re.node {
             *syn = RangeSyntax::DotDotEq;
             self.struct_span_err(re.span, "range-to patterns with `...` are not allowed")
                 .span_suggestion_short(
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 73de86820d8..1b56cd72db0 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -563,9 +563,9 @@ impl<'a> Parser<'a> {
         };
 
         let mut eat_semi = true;
-        match stmt.kind {
+        match &mut stmt.kind {
             // Expression without semicolon.
-            StmtKind::Expr(ref mut expr)
+            StmtKind::Expr(expr)
                 if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) => {
                 // Just check for errors and recover; do not eat semicolon yet.
                 // `expect_one_of` returns PResult<'a, bool /* recovered */>
@@ -611,7 +611,7 @@ impl<'a> Parser<'a> {
                 }
             }
             StmtKind::Expr(_) | StmtKind::MacCall(_) => {}
-            StmtKind::Local(ref mut local) if let Err(e) = self.expect_semi() => {
+            StmtKind::Local(local) if let Err(e) = self.expect_semi() => {
                 // We might be at the `,` in `let x = foo<bar, baz>;`. Try to recover.
                 match &mut local.kind {
                     LocalKind::Init(expr) | LocalKind::InitElse(expr, _) => {
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index fecf67cb596..b7206b57642 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -536,7 +536,7 @@ impl<'a> Parser<'a> {
         };
         let span_start = self.token.span;
         let ast::FnHeader { ext, unsafety, constness, asyncness } =
-            self.parse_fn_front_matter(&inherited_vis)?;
+            self.parse_fn_front_matter(&inherited_vis, Case::Sensitive)?;
         if self.may_recover() && self.token.kind == TokenKind::Lt {
             self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
         }
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 58e1fe937a6..2234837050b 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -922,8 +922,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 //    v     v
                 //   (  succ  )
                 //
-                let else_ln =
-                    self.propagate_through_opt_expr(else_opt.as_ref().map(|e| &**e), succ);
+                let else_ln = self.propagate_through_opt_expr(else_opt.as_deref(), succ);
                 let then_ln = self.propagate_through_expr(&then, succ);
                 let ln = self.live_node(expr.hir_id, expr.span);
                 self.init_from_succ(ln, else_ln);
@@ -966,7 +965,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
             hir::ExprKind::Ret(ref o_e) => {
                 // Ignore succ and subst exit_ln.
-                self.propagate_through_opt_expr(o_e.as_ref().map(|e| &**e), self.exit_ln)
+                self.propagate_through_opt_expr(o_e.as_deref(), self.exit_ln)
             }
 
             hir::ExprKind::Break(label, ref opt_expr) => {
@@ -981,7 +980,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 // look it up in the break loop nodes table
 
                 match target {
-                    Some(b) => self.propagate_through_opt_expr(opt_expr.as_ref().map(|e| &**e), b),
+                    Some(b) => self.propagate_through_opt_expr(opt_expr.as_deref(), b),
                     None => span_bug!(expr.span, "`break` to unknown label"),
                 }
             }
@@ -1026,7 +1025,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             hir::ExprKind::Array(ref exprs) => self.propagate_through_exprs(exprs, succ),
 
             hir::ExprKind::Struct(_, ref fields, ref with_expr) => {
-                let succ = self.propagate_through_opt_expr(with_expr.as_ref().map(|e| &**e), succ);
+                let succ = self.propagate_through_opt_expr(with_expr.as_deref(), succ);
                 fields
                     .iter()
                     .rev()
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 18cb0e0ca0b..e6df6956158 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -32,8 +32,7 @@ use rustc_query_system::query::*;
 #[cfg(parallel_compiler)]
 pub use rustc_query_system::query::{deadlock, QueryContext};
 
-mod keys;
-use keys::Key;
+use rustc_middle::query::Key;
 
 pub use rustc_query_system::query::QueryConfig;
 pub(crate) use rustc_query_system::query::QueryVTable;
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 992e777904e..99edaa04162 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -2,7 +2,6 @@
 //! generate the actual methods on tcx which find and execute the provider,
 //! manage the caches, and so forth.
 
-use crate::keys::Key;
 use crate::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
 use crate::profiling_support::QueryKeyStringCache;
 use crate::{on_disk_cache, Queries};
@@ -12,6 +11,7 @@ use rustc_errors::{Diagnostic, Handler};
 use rustc_middle::dep_graph::{
     self, DepKind, DepKindStruct, DepNode, DepNodeIndex, SerializedDepNodeIndex,
 };
+use rustc_middle::query::Key;
 use rustc_middle::ty::tls::{self, ImplicitCtxt};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index d86c0bebdcd..e90afc591b5 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -667,7 +667,7 @@ impl<K: DepKind> DepGraph<K> {
             None => {}
         }
 
-        if !qcx.dep_context().sess().has_errors_or_delayed_span_bugs() {
+        if let None = qcx.dep_context().sess().has_errors_or_delayed_span_bugs() {
             panic!("try_mark_previous_green() - Forcing the DepNode should have set its color")
         }
 
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index 85c5af72ef5..cdd43572422 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -8,13 +8,17 @@ use rustc_data_structures::sharded::Sharded;
 #[cfg(not(parallel_compiler))]
 use rustc_data_structures::sync::Lock;
 use rustc_data_structures::sync::WorkerLocal;
+use rustc_index::vec::{Idx, IndexVec};
 use std::default::Default;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
 
-pub trait CacheSelector<K, V> {
-    type Cache;
+pub trait CacheSelector<'tcx, V> {
+    type Cache
+    where
+        V: Clone;
+    type ArenaCache;
 }
 
 pub trait QueryStorage {
@@ -47,10 +51,13 @@ pub trait QueryCache: QueryStorage + Sized {
     fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex));
 }
 
-pub struct DefaultCacheSelector;
+pub struct DefaultCacheSelector<K>(PhantomData<K>);
 
-impl<K: Eq + Hash, V: Clone> CacheSelector<K, V> for DefaultCacheSelector {
-    type Cache = DefaultCache<K, V>;
+impl<'tcx, K: Eq + Hash, V: 'tcx> CacheSelector<'tcx, V> for DefaultCacheSelector<K> {
+    type Cache = DefaultCache<K, V>
+    where
+        V: Clone;
+    type ArenaCache = ArenaCache<'tcx, K, V>;
 }
 
 pub struct DefaultCache<K, V> {
@@ -134,12 +141,6 @@ where
     }
 }
 
-pub struct ArenaCacheSelector<'tcx>(PhantomData<&'tcx ()>);
-
-impl<'tcx, K: Eq + Hash, V: 'tcx> CacheSelector<K, V> for ArenaCacheSelector<'tcx> {
-    type Cache = ArenaCache<'tcx, K, V>;
-}
-
 pub struct ArenaCache<'tcx, K, V> {
     arena: WorkerLocal<TypedArena<(V, DepNodeIndex)>>,
     #[cfg(parallel_compiler)]
@@ -224,3 +225,183 @@ where
         }
     }
 }
+
+pub struct VecCacheSelector<K>(PhantomData<K>);
+
+impl<'tcx, K: Idx, V: 'tcx> CacheSelector<'tcx, V> for VecCacheSelector<K> {
+    type Cache = VecCache<K, V>
+    where
+        V: Clone;
+    type ArenaCache = VecArenaCache<'tcx, K, V>;
+}
+
+pub struct VecCache<K: Idx, V> {
+    #[cfg(parallel_compiler)]
+    cache: Sharded<IndexVec<K, Option<(V, DepNodeIndex)>>>,
+    #[cfg(not(parallel_compiler))]
+    cache: Lock<IndexVec<K, Option<(V, DepNodeIndex)>>>,
+}
+
+impl<K: Idx, V> Default for VecCache<K, V> {
+    fn default() -> Self {
+        VecCache { cache: Default::default() }
+    }
+}
+
+impl<K: Eq + Idx, V: Clone + Debug> QueryStorage for VecCache<K, V> {
+    type Value = V;
+    type Stored = V;
+
+    #[inline]
+    fn store_nocache(&self, value: Self::Value) -> Self::Stored {
+        // We have no dedicated storage
+        value
+    }
+}
+
+impl<K, V> QueryCache for VecCache<K, V>
+where
+    K: Eq + Idx + Clone + Debug,
+    V: Clone + Debug,
+{
+    type Key = K;
+
+    #[inline(always)]
+    fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
+    where
+        OnHit: FnOnce(&V, DepNodeIndex) -> R,
+    {
+        #[cfg(parallel_compiler)]
+        let lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
+        #[cfg(not(parallel_compiler))]
+        let lock = self.cache.lock();
+        if let Some(Some(value)) = lock.get(*key) {
+            let hit_result = on_hit(&value.0, value.1);
+            Ok(hit_result)
+        } else {
+            Err(())
+        }
+    }
+
+    #[inline]
+    fn complete(&self, key: K, value: V, index: DepNodeIndex) -> Self::Stored {
+        #[cfg(parallel_compiler)]
+        let mut lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
+        #[cfg(not(parallel_compiler))]
+        let mut lock = self.cache.lock();
+        lock.insert(key, (value.clone(), index));
+        value
+    }
+
+    fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
+        #[cfg(parallel_compiler)]
+        {
+            let shards = self.cache.lock_shards();
+            for shard in shards.iter() {
+                for (k, v) in shard.iter_enumerated() {
+                    if let Some(v) = v {
+                        f(&k, &v.0, v.1);
+                    }
+                }
+            }
+        }
+        #[cfg(not(parallel_compiler))]
+        {
+            let map = self.cache.lock();
+            for (k, v) in map.iter_enumerated() {
+                if let Some(v) = v {
+                    f(&k, &v.0, v.1);
+                }
+            }
+        }
+    }
+}
+
+pub struct VecArenaCache<'tcx, K: Idx, V> {
+    arena: WorkerLocal<TypedArena<(V, DepNodeIndex)>>,
+    #[cfg(parallel_compiler)]
+    cache: Sharded<IndexVec<K, Option<&'tcx (V, DepNodeIndex)>>>,
+    #[cfg(not(parallel_compiler))]
+    cache: Lock<IndexVec<K, Option<&'tcx (V, DepNodeIndex)>>>,
+}
+
+impl<'tcx, K: Idx, V> Default for VecArenaCache<'tcx, K, V> {
+    fn default() -> Self {
+        VecArenaCache {
+            arena: WorkerLocal::new(|_| TypedArena::default()),
+            cache: Default::default(),
+        }
+    }
+}
+
+impl<'tcx, K: Eq + Idx, V: Debug + 'tcx> QueryStorage for VecArenaCache<'tcx, K, V> {
+    type Value = V;
+    type Stored = &'tcx V;
+
+    #[inline]
+    fn store_nocache(&self, value: Self::Value) -> Self::Stored {
+        let value = self.arena.alloc((value, DepNodeIndex::INVALID));
+        let value = unsafe { &*(&value.0 as *const _) };
+        &value
+    }
+}
+
+impl<'tcx, K, V: 'tcx> QueryCache for VecArenaCache<'tcx, K, V>
+where
+    K: Eq + Idx + Clone + Debug,
+    V: Debug,
+{
+    type Key = K;
+
+    #[inline(always)]
+    fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
+    where
+        OnHit: FnOnce(&&'tcx V, DepNodeIndex) -> R,
+    {
+        #[cfg(parallel_compiler)]
+        let lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
+        #[cfg(not(parallel_compiler))]
+        let lock = self.cache.lock();
+        if let Some(Some(value)) = lock.get(*key) {
+            let hit_result = on_hit(&&value.0, value.1);
+            Ok(hit_result)
+        } else {
+            Err(())
+        }
+    }
+
+    #[inline]
+    fn complete(&self, key: K, value: V, index: DepNodeIndex) -> Self::Stored {
+        let value = self.arena.alloc((value, index));
+        let value = unsafe { &*(value as *const _) };
+        #[cfg(parallel_compiler)]
+        let mut lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
+        #[cfg(not(parallel_compiler))]
+        let mut lock = self.cache.lock();
+        lock.insert(key, value);
+        &value.0
+    }
+
+    fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
+        #[cfg(parallel_compiler)]
+        {
+            let shards = self.cache.lock_shards();
+            for shard in shards.iter() {
+                for (k, v) in shard.iter_enumerated() {
+                    if let Some(v) = v {
+                        f(&k, &v.0, v.1);
+                    }
+                }
+            }
+        }
+        #[cfg(not(parallel_compiler))]
+        {
+            let map = self.cache.lock();
+            for (k, v) in map.iter_enumerated() {
+                if let Some(v) = v {
+                    f(&k, &v.0, v.1);
+                }
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index 94adef41e68..7f3dc50d234 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -8,7 +8,7 @@ pub use self::job::{print_query_stack, QueryInfo, QueryJob, QueryJobId, QueryJob
 
 mod caches;
 pub use self::caches::{
-    ArenaCacheSelector, CacheSelector, DefaultCacheSelector, QueryCache, QueryStorage,
+    CacheSelector, DefaultCacheSelector, QueryCache, QueryStorage, VecCacheSelector,
 };
 
 mod config;
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index e7e419c9b42..fff3f0467df 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -30,7 +30,7 @@ use rustc_middle::metadata::ModChild;
 use rustc_middle::ty::{self, DefIdTree};
 use rustc_session::cstore::CrateStore;
 use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
-use rustc_span::source_map::{respan, Spanned};
+use rustc_span::source_map::respan;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
 
@@ -329,10 +329,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             .iter()
             .map(|field| respan(field.span, field.ident.map_or(kw::Empty, |ident| ident.name)))
             .collect();
-        self.insert_field_names(def_id, field_names);
+        self.r.field_names.insert(def_id, field_names);
     }
 
-    fn insert_field_names(&mut self, def_id: DefId, field_names: Vec<Spanned<Symbol>>) {
+    fn insert_field_names_extern(&mut self, def_id: DefId) {
+        let field_names =
+            self.r.cstore().struct_field_names_untracked(def_id, self.r.session).collect();
         self.r.field_names.insert(def_id, field_names);
     }
 
@@ -747,7 +749,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
 
                 // If this is a tuple or unit struct, define a name
                 // in the value namespace as well.
-                if let Some(ctor_node_id) = vdata.ctor_id() {
+                if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(vdata) {
                     // If the structure is marked as non_exhaustive then lower the visibility
                     // to within the crate.
                     let mut ctor_vis = if vis.is_public()
@@ -773,10 +775,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                         ret_fields.push(field_vis.to_def_id());
                     }
                     let ctor_def_id = self.r.local_def_id(ctor_node_id);
-                    let ctor_res = Res::Def(
-                        DefKind::Ctor(CtorOf::Struct, CtorKind::from_ast(vdata)),
-                        ctor_def_id.to_def_id(),
-                    );
+                    let ctor_res =
+                        Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id.to_def_id());
                     self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion));
                     self.r.visibilities.insert(ctor_def_id, ctor_vis);
 
@@ -997,10 +997,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         let cstore = self.r.cstore();
         match res {
             Res::Def(DefKind::Struct, def_id) => {
-                let field_names =
-                    cstore.struct_field_names_untracked(def_id, self.r.session).collect();
-                let ctor = cstore.ctor_def_id_and_kind_untracked(def_id);
-                if let Some((ctor_def_id, ctor_kind)) = ctor {
+                if let Some((ctor_kind, ctor_def_id)) = cstore.ctor_untracked(def_id) {
                     let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
                     let ctor_vis = cstore.visibility_untracked(ctor_def_id);
                     let field_visibilities =
@@ -1009,13 +1006,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                         .struct_constructors
                         .insert(def_id, (ctor_res, ctor_vis, field_visibilities));
                 }
-                self.insert_field_names(def_id, field_names);
-            }
-            Res::Def(DefKind::Union, def_id) => {
-                let field_names =
-                    cstore.struct_field_names_untracked(def_id, self.r.session).collect();
-                self.insert_field_names(def_id, field_names);
+                self.insert_field_names_extern(def_id)
             }
+            Res::Def(DefKind::Union, def_id) => self.insert_field_names_extern(def_id),
             Res::Def(DefKind::AssocFn, def_id) => {
                 if cstore.fn_has_self_parameter_untracked(def_id, self.r.session) {
                     self.r.has_self.insert(def_id);
@@ -1517,20 +1510,16 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
         };
 
         // Define a constructor name in the value namespace.
-        // Braced variants, unlike structs, generate unusable names in
-        // value namespace, they are reserved for possible future use.
-        // It's ok to use the variant's id as a ctor id since an
-        // error will be reported on any use of such resolution anyway.
-        let ctor_node_id = variant.data.ctor_id().unwrap_or(variant.id);
-        let ctor_def_id = self.r.local_def_id(ctor_node_id);
-        let ctor_kind = CtorKind::from_ast(&variant.data);
-        let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id.to_def_id());
-        self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));
-        if ctor_def_id != def_id {
+        if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(&variant.data) {
+            let ctor_def_id = self.r.local_def_id(ctor_node_id);
+            let ctor_res =
+                Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id.to_def_id());
+            self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));
             self.r.visibilities.insert(ctor_def_id, ctor_vis);
         }
+
         // Record field names for error reporting.
-        self.insert_field_names_local(ctor_def_id.to_def_id(), &variant.data);
+        self.insert_field_names_local(def_id.to_def_id(), &variant.data);
 
         visit::walk_variant(self, variant);
     }
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index b1cee06849d..bf2428e1731 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -118,8 +118,8 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
                 match i.kind {
                     ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
                         // If this is a unit or tuple-like struct, register the constructor.
-                        if let Some(ctor_hir_id) = struct_def.ctor_id() {
-                            this.create_def(ctor_hir_id, DefPathData::Ctor, i.span);
+                        if let Some(ctor_node_id) = struct_def.ctor_node_id() {
+                            this.create_def(ctor_node_id, DefPathData::Ctor, i.span);
                         }
                     }
                     _ => {}
@@ -131,12 +131,9 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
 
     fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
         if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind {
-            if let Async::Yes { closure_id, return_impl_trait_id, .. } = sig.header.asyncness {
+            if let Async::Yes { closure_id, .. } = sig.header.asyncness {
                 self.visit_generics(generics);
 
-                let return_impl_trait_id =
-                    self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span);
-
                 // For async functions, we need to create their inner defs inside of a
                 // closure to match their desugared representation. Besides that,
                 // we must mirror everything that `visit::walk_fn` below does.
@@ -144,9 +141,7 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
                 for param in &sig.decl.inputs {
                     self.visit_param(param);
                 }
-                self.with_parent(return_impl_trait_id, |this| {
-                    this.visit_fn_ret_ty(&sig.decl.output)
-                });
+                self.visit_fn_ret_ty(&sig.decl.output);
                 // If this async fn has no body (i.e. it's an async fn signature in a trait)
                 // then the closure_def will never be used, and we should avoid generating a
                 // def-id for it.
@@ -196,8 +191,8 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
         }
         let def = self.create_def(v.id, DefPathData::TypeNs(v.ident.name), v.span);
         self.with_parent(def, |this| {
-            if let Some(ctor_hir_id) = v.data.ctor_id() {
-                this.create_def(ctor_hir_id, DefPathData::Ctor, v.span);
+            if let Some(ctor_node_id) = v.data.ctor_node_id() {
+                this.create_def(ctor_node_id, DefPathData::Ctor, v.span);
             }
             visit::walk_variant(this, v)
         });
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 82dcc7efb1b..3aa8d52db03 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -7,8 +7,10 @@ use rustc_ast::EnumDef;
 use rustc_data_structures::intern::Interned;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::def_id::CRATE_DEF_ID;
-use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
-use rustc_middle::ty::Visibility;
+use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility};
+use rustc_middle::middle::privacy::{IntoDefIdTree, Level};
+use rustc_middle::ty::{DefIdTree, Visibility};
+use std::mem;
 
 type ImportId<'a> = Interned<'a, NameBinding<'a>>;
 
@@ -29,13 +31,49 @@ impl ParentId<'_> {
 
 pub struct EffectiveVisibilitiesVisitor<'r, 'a> {
     r: &'r mut Resolver<'a>,
+    def_effective_visibilities: EffectiveVisibilities,
     /// While walking import chains we need to track effective visibilities per-binding, and def id
     /// keys in `Resolver::effective_visibilities` are not enough for that, because multiple
     /// bindings can correspond to a single def id in imports. So we keep a separate table.
     import_effective_visibilities: EffectiveVisibilities<ImportId<'a>>,
+    // It's possible to recalculate this at any point, but it's relatively expensive.
+    current_private_vis: Visibility,
     changed: bool,
 }
 
+impl Resolver<'_> {
+    fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId {
+        self.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local()
+    }
+
+    fn private_vis_import(&mut self, binding: ImportId<'_>) -> Visibility {
+        let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() };
+        Visibility::Restricted(
+            import
+                .id()
+                .map(|id| self.nearest_normal_mod(self.local_def_id(id)))
+                .unwrap_or(CRATE_DEF_ID),
+        )
+    }
+
+    fn private_vis_def(&mut self, def_id: LocalDefId) -> Visibility {
+        // For mod items `nearest_normal_mod` returns its argument, but we actually need its parent.
+        let normal_mod_id = self.nearest_normal_mod(def_id);
+        if normal_mod_id == def_id {
+            self.opt_local_parent(def_id).map_or(Visibility::Public, Visibility::Restricted)
+        } else {
+            Visibility::Restricted(normal_mod_id)
+        }
+    }
+}
+
+impl<'a, 'b> IntoDefIdTree for &'b mut Resolver<'a> {
+    type Tree = &'b Resolver<'a>;
+    fn tree(self) -> Self::Tree {
+        self
+    }
+}
+
 impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
     /// Fills the `Resolver::effective_visibilities` table with public & exported items
     /// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we
@@ -43,17 +81,21 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
     pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) {
         let mut visitor = EffectiveVisibilitiesVisitor {
             r,
+            def_effective_visibilities: Default::default(),
             import_effective_visibilities: Default::default(),
+            current_private_vis: Visibility::Public,
             changed: false,
         };
 
         visitor.update(CRATE_DEF_ID, CRATE_DEF_ID);
+        visitor.current_private_vis = Visibility::Restricted(CRATE_DEF_ID);
         visitor.set_bindings_effective_visibilities(CRATE_DEF_ID);
 
         while visitor.changed {
             visitor.changed = false;
             visit::walk_crate(&mut visitor, krate);
         }
+        visitor.r.effective_visibilities = visitor.def_effective_visibilities;
 
         // Update visibilities for import def ids. These are not used during the
         // `EffectiveVisibilitiesVisitor` pass, because we have more detailed binding-based
@@ -90,10 +132,6 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
         info!("resolve::effective_visibilities: {:#?}", r.effective_visibilities);
     }
 
-    fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId {
-        self.r.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local()
-    }
-
     /// Update effective visibilities of bindings in the given module,
     /// including their whole reexport chains.
     fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) {
@@ -122,62 +160,47 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
         }
     }
 
-    fn effective_vis(&self, parent_id: ParentId<'a>) -> Option<EffectiveVisibility> {
-        match parent_id {
-            ParentId::Def(def_id) => self.r.effective_visibilities.effective_vis(def_id),
-            ParentId::Import(binding) => self.import_effective_visibilities.effective_vis(binding),
-        }
-        .copied()
+    fn cheap_private_vis(&self, parent_id: ParentId<'_>) -> Option<Visibility> {
+        matches!(parent_id, ParentId::Def(_)).then_some(self.current_private_vis)
     }
 
-    /// The update is guaranteed to not change the table and we can skip it.
-    fn is_noop_update(
-        &self,
-        parent_id: ParentId<'a>,
-        nominal_vis: Visibility,
-        default_vis: Visibility,
-    ) -> bool {
-        nominal_vis == default_vis
-            || match parent_id {
-                ParentId::Def(def_id) => self.r.visibilities[&def_id],
-                ParentId::Import(binding) => binding.vis.expect_local(),
-            } == default_vis
+    fn effective_vis_or_private(&mut self, parent_id: ParentId<'a>) -> EffectiveVisibility {
+        // Private nodes are only added to the table for caching, they could be added or removed at
+        // any moment without consequences, so we don't set `changed` to true when adding them.
+        *match parent_id {
+            ParentId::Def(def_id) => self
+                .def_effective_visibilities
+                .effective_vis_or_private(def_id, || self.r.private_vis_def(def_id)),
+            ParentId::Import(binding) => self
+                .import_effective_visibilities
+                .effective_vis_or_private(binding, || self.r.private_vis_import(binding)),
+        }
     }
 
     fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) {
-        let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() };
         let nominal_vis = binding.vis.expect_local();
-        let default_vis = Visibility::Restricted(
-            import
-                .id()
-                .map(|id| self.nearest_normal_mod(self.r.local_def_id(id)))
-                .unwrap_or(CRATE_DEF_ID),
-        );
-        if self.is_noop_update(parent_id, nominal_vis, default_vis) {
-            return;
-        }
+        let private_vis = self.cheap_private_vis(parent_id);
+        let inherited_eff_vis = self.effective_vis_or_private(parent_id);
         self.changed |= self.import_effective_visibilities.update(
             binding,
             nominal_vis,
-            default_vis,
-            self.effective_vis(parent_id),
+            |r| (private_vis.unwrap_or_else(|| r.private_vis_import(binding)), r),
+            inherited_eff_vis,
             parent_id.level(),
-            ResolverTree(&self.r.definitions, &self.r.crate_loader),
+            &mut *self.r,
         );
     }
 
     fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) {
-        let default_vis = Visibility::Restricted(self.nearest_normal_mod(def_id));
-        if self.is_noop_update(parent_id, nominal_vis, default_vis) {
-            return;
-        }
-        self.changed |= self.r.effective_visibilities.update(
+        let private_vis = self.cheap_private_vis(parent_id);
+        let inherited_eff_vis = self.effective_vis_or_private(parent_id);
+        self.changed |= self.def_effective_visibilities.update(
             def_id,
             nominal_vis,
-            if def_id == CRATE_DEF_ID { Visibility::Public } else { default_vis },
-            self.effective_vis(parent_id),
+            |r| (private_vis.unwrap_or_else(|| r.private_vis_def(def_id)), r),
+            inherited_eff_vis,
             parent_id.level(),
-            ResolverTree(&self.r.definitions, &self.r.crate_loader),
+            &mut *self.r,
         );
     }
 
@@ -201,8 +224,11 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> {
             ),
 
             ast::ItemKind::Mod(..) => {
+                let prev_private_vis =
+                    mem::replace(&mut self.current_private_vis, Visibility::Restricted(def_id));
                 self.set_bindings_effective_visibilities(def_id);
                 visit::walk_item(self, item);
+                self.current_private_vis = prev_private_vis;
             }
 
             ast::ItemKind::Enum(EnumDef { ref variants }, _) => {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 5072d2aad16..8555e4c8626 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -3841,7 +3841,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 }
             }
 
-            ExprKind::Loop(ref block, label) => self.resolve_labeled_block(label, expr.id, &block),
+            ExprKind::Loop(ref block, label, _) => {
+                self.resolve_labeled_block(label, expr.id, &block)
+            }
 
             ExprKind::While(ref cond, ref block, label) => {
                 self.with_resolved_label(label, expr.id, |this| {
@@ -3912,7 +3914,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 visit::walk_expr(self, expr);
                 self.diagnostic_metadata.current_type_ascription.pop();
             }
-            // `async |x| ...` gets desugared to `|x| future_from_generator(|| ...)`, so we need to
+            // `async |x| ...` gets desugared to `|x| async {...}`, so we need to
             // resolve the arguments within the proper scopes so that usages of them inside the
             // closure are detected as upvars rather than normal closure arg usages.
             ExprKind::Closure(box ast::Closure {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index e0c927dd1e7..9c95adc628b 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -21,6 +21,7 @@ use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::PrimTy;
+use rustc_middle::ty::DefIdTree;
 use rustc_session::lint;
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
@@ -1442,13 +1443,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
 
                 err.span_label(span, "constructor is not visible here due to private fields");
             }
-            (
-                Res::Def(
-                    DefKind::Union | DefKind::Variant | DefKind::Ctor(_, CtorKind::Fictive),
-                    def_id,
-                ),
-                _,
-            ) if ns == ValueNS => {
+            (Res::Def(DefKind::Union | DefKind::Variant, def_id), _) if ns == ValueNS => {
                 bad_struct_syntax_suggestion(def_id);
             }
             (Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id), _) if ns == ValueNS => {
@@ -1468,7 +1463,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                     _ => return false,
                 }
             }
-            (Res::Def(DefKind::Ctor(_, CtorKind::Fn), def_id), _) if ns == ValueNS => {
+            (Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_def_id), _) if ns == ValueNS => {
+                let def_id = self.r.parent(ctor_def_id);
                 if let Some(span) = self.def_span(def_id) {
                     err.span_label(span, &format!("`{}` defined here", path_str));
                 }
@@ -1959,11 +1955,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                 ));
             }
         } else {
-            let needs_placeholder = |def_id: DefId, kind: CtorKind| {
+            let needs_placeholder = |ctor_def_id: DefId, kind: CtorKind| {
+                let def_id = self.r.parent(ctor_def_id);
                 let has_no_fields = self.r.field_names.get(&def_id).map_or(false, |f| f.is_empty());
                 match kind {
                     CtorKind::Const => false,
-                    CtorKind::Fn | CtorKind::Fictive if has_no_fields => false,
+                    CtorKind::Fn if has_no_fields => false,
                     _ => true,
                 }
             };
@@ -1975,7 +1972,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                 .map(|(variant, kind)| match kind {
                     CtorKind::Const => variant,
                     CtorKind::Fn => format!("({}())", variant),
-                    CtorKind::Fictive => format!("({} {{}})", variant),
                 })
                 .collect::<Vec<_>>();
             let no_suggestable_variant = suggestable_variants.is_empty();
@@ -2001,7 +1997,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                 .map(|(variant, _, kind)| (path_names_to_string(variant), kind))
                 .filter_map(|(variant, kind)| match kind {
                     CtorKind::Fn => Some(format!("({}(/* fields */))", variant)),
-                    CtorKind::Fictive => Some(format!("({} {{ /* fields */ }})", variant)),
                     _ => None,
                 })
                 .collect::<Vec<_>>();
diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs
index 0e579379ec8..fae20c2ba5f 100644
--- a/compiler/rustc_save_analysis/src/dump_visitor.rs
+++ b/compiler/rustc_save_analysis/src/dump_visitor.rs
@@ -1029,7 +1029,7 @@ impl<'tcx> DumpVisitor<'tcx> {
                                 trait_item.hir_id(),
                                 trait_item.ident,
                                 Some(bounds),
-                                default_ty.as_ref().map(|ty| &**ty),
+                                default_ty.as_deref(),
                                 &self.save_ctxt,
                             ),
                             attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index be084adb7b7..3b1b33aa095 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -11,7 +11,7 @@ use crate::{lint, HashStableContext};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 
 use rustc_data_structures::stable_hasher::ToStableHashKey;
-use rustc_target::abi::{Align, TargetDataLayout};
+use rustc_target::abi::Align;
 use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo};
 use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
 
@@ -900,7 +900,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
     let min_atomic_width = sess.target.min_atomic_width();
     let max_atomic_width = sess.target.max_atomic_width();
     let atomic_cas = sess.target.atomic_cas;
-    let layout = TargetDataLayout::parse(&sess.target).unwrap_or_else(|err| {
+    let layout = sess.target.parse_data_layout().unwrap_or_else(|err| {
         sess.emit_fatal(err);
     });
 
@@ -1480,7 +1480,7 @@ pub fn get_cmd_lint_options(
 
 /// Parses the `--color` flag.
 pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
-    match matches.opt_str("color").as_ref().map(|s| &s[..]) {
+    match matches.opt_str("color").as_deref() {
         Some("auto") => ColorConfig::Auto,
         Some("always") => ColorConfig::Always,
         Some("never") => ColorConfig::Never,
@@ -1589,7 +1589,7 @@ pub fn parse_error_format(
     // is unstable, it will not be present. We have to use `opts_present` not
     // `opt_present` because the latter will panic.
     let error_format = if matches.opts_present(&["error-format".to_owned()]) {
-        match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
+        match matches.opt_str("error-format").as_deref() {
             None | Some("human") => {
                 ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color))
             }
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index d602acec53e..e99e460913e 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -538,9 +538,12 @@ impl Session {
     pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
         self.diagnostic().has_errors()
     }
-    pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
+    pub fn has_errors_or_delayed_span_bugs(&self) -> Option<ErrorGuaranteed> {
         self.diagnostic().has_errors_or_delayed_span_bugs()
     }
+    pub fn is_compilation_going_to_fail(&self) -> Option<ErrorGuaranteed> {
+        self.diagnostic().is_compilation_going_to_fail()
+    }
     pub fn abort_if_errors(&self) {
         self.diagnostic().abort_if_errors();
     }
@@ -1357,7 +1360,7 @@ pub fn build_session(
         let profiler = SelfProfiler::new(
             directory,
             sopts.crate_name.as_deref(),
-            sopts.unstable_opts.self_profile_events.as_ref().map(|xs| &xs[..]),
+            sopts.unstable_opts.self_profile_events.as_deref(),
             &sopts.unstable_opts.self_profile_counter,
         );
         match profiler {
@@ -1391,7 +1394,7 @@ pub fn build_session(
         local_crate_source_file.map(|path| file_path_mapping.map_prefix(path).0);
 
     let optimization_fuel = Lock::new(OptimizationFuel {
-        remaining: sopts.unstable_opts.fuel.as_ref().map_or(0, |i| i.1),
+        remaining: sopts.unstable_opts.fuel.as_ref().map_or(0, |&(_, i)| i),
         out_of_fuel: false,
     });
     let print_fuel = AtomicU64::new(0);
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 322c7104be4..7ccfa600ec3 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -217,9 +217,7 @@ impl RealFileName {
     pub fn local_path(&self) -> Option<&Path> {
         match self {
             RealFileName::LocalPath(p) => Some(p),
-            RealFileName::Remapped { local_path: p, virtual_name: _ } => {
-                p.as_ref().map(PathBuf::as_path)
-            }
+            RealFileName::Remapped { local_path, virtual_name: _ } => local_path.as_deref(),
         }
     }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 29312a21b4d..aba301dce10 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -264,6 +264,7 @@ symbols! {
         Relaxed,
         Release,
         Result,
+        ResumeTy,
         Return,
         Right,
         Rust,
@@ -728,7 +729,6 @@ symbols! {
         frem_fast,
         from,
         from_desugaring,
-        from_generator,
         from_iter,
         from_method,
         from_output,
@@ -779,6 +779,7 @@ symbols! {
         i64,
         i8,
         ident,
+        identity_future,
         if_let,
         if_let_guard,
         if_while_or_patterns,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 6ad0a7d2911..d1a2aee207d 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -689,15 +689,15 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                         self.push("V");
                         self = self.print_def_path(variant_def.def_id, substs)?;
 
-                        match variant_def.ctor_kind {
-                            CtorKind::Const => {
+                        match variant_def.ctor_kind() {
+                            Some(CtorKind::Const) => {
                                 self.push("U");
                             }
-                            CtorKind::Fn => {
+                            Some(CtorKind::Fn) => {
                                 self.push("T");
                                 self = print_field_list(self)?;
                             }
-                            CtorKind::Fictive => {
+                            None => {
                                 self.push("S");
                                 for (field_def, field) in iter::zip(&variant_def.fields, fields) {
                                     // HACK(eddyb) this mimics `path_append`,
diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml
index fc37fdb1c43..568c916a163 100644
--- a/compiler/rustc_target/Cargo.toml
+++ b/compiler/rustc_target/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 bitflags = "1.2.1"
 tracing = "0.1"
 serde_json = "1.0.59"
+rustc_abi = { path = "../rustc_abi" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_index = { path = "../rustc_index" }
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 0c559ec04a4..a5ffaebea0b 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -262,7 +262,7 @@ impl CastTarget {
         let mut size = self.rest.total;
         for i in 0..self.prefix.iter().count() {
             match self.prefix[i] {
-                Some(v) => size += Size { raw: v.size.bytes() },
+                Some(v) => size += v.size,
                 None => {}
             }
         }
diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs
index 1b74959ad17..ec8f20fe692 100644
--- a/compiler/rustc_target/src/abi/call/sparc64.rs
+++ b/compiler/rustc_target/src/abi/call/sparc64.rs
@@ -87,8 +87,8 @@ where
         _ => {}
     }
 
-    if (offset.raw % 4) != 0 && scalar2.primitive().is_float() {
-        offset.raw += 4 - (offset.raw % 4);
+    if (offset.bytes() % 4) != 0 && scalar2.primitive().is_float() {
+        offset += Size::from_bytes(4 - (offset.bytes() % 4));
     }
     data = arg_scalar(cx, &scalar2, offset, data);
     return data;
@@ -169,14 +169,14 @@ where
                     has_float: false,
                     arg_attribute: ArgAttribute::default(),
                 },
-                Size { raw: 0 },
+                Size::ZERO,
             );
 
             if data.has_float {
                 // Structure { float, int, int } doesn't like to be handled like
                 // { float, long int }. Other way around it doesn't mind.
                 if data.last_offset < arg.layout.size
-                    && (data.last_offset.raw % 8) != 0
+                    && (data.last_offset.bytes() % 8) != 0
                     && data.prefix_index < data.prefix.len()
                 {
                     data.prefix[data.prefix_index] = Some(Reg::i32());
@@ -185,7 +185,7 @@ where
                 }
 
                 let mut rest_size = arg.layout.size - data.last_offset;
-                if (rest_size.raw % 8) != 0 && data.prefix_index < data.prefix.len() {
+                if (rest_size.bytes() % 8) != 0 && data.prefix_index < data.prefix.len() {
                     data.prefix[data.prefix_index] = Some(Reg::i32());
                     rest_size = rest_size - Reg::i32().size;
                 }
@@ -214,13 +214,13 @@ where
     C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
-        classify_arg(cx, &mut fn_abi.ret, Size { raw: 32 });
+        classify_arg(cx, &mut fn_abi.ret, Size::from_bytes(32));
     }
 
     for arg in fn_abi.args.iter_mut() {
         if arg.is_ignore() {
             continue;
         }
-        classify_arg(cx, arg, Size { raw: 16 });
+        classify_arg(cx, arg, Size::from_bytes(16));
     }
 }
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index decbefc2f7c..53c9878ab87 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -2,284 +2,16 @@ pub use Integer::*;
 pub use Primitive::*;
 
 use crate::json::{Json, ToJson};
-use crate::spec::Target;
 
-use std::convert::{TryFrom, TryInto};
 use std::fmt;
-use std::iter::Step;
-use std::num::{NonZeroUsize, ParseIntError};
-use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
-use std::str::FromStr;
+use std::ops::Deref;
 
 use rustc_data_structures::intern::Interned;
-use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable_Generic;
 
 pub mod call;
 
-/// Parsed [Data layout](https://llvm.org/docs/LangRef.html#data-layout)
-/// for a target, which contains everything needed to compute layouts.
-pub struct TargetDataLayout {
-    pub endian: Endian,
-    pub i1_align: AbiAndPrefAlign,
-    pub i8_align: AbiAndPrefAlign,
-    pub i16_align: AbiAndPrefAlign,
-    pub i32_align: AbiAndPrefAlign,
-    pub i64_align: AbiAndPrefAlign,
-    pub i128_align: AbiAndPrefAlign,
-    pub f32_align: AbiAndPrefAlign,
-    pub f64_align: AbiAndPrefAlign,
-    pub pointer_size: Size,
-    pub pointer_align: AbiAndPrefAlign,
-    pub aggregate_align: AbiAndPrefAlign,
-
-    /// Alignments for vector types.
-    pub vector_align: Vec<(Size, AbiAndPrefAlign)>,
-
-    pub instruction_address_space: AddressSpace,
-
-    /// Minimum size of #[repr(C)] enums (default I32 bits)
-    pub c_enum_min_size: Integer,
-}
-
-impl Default for TargetDataLayout {
-    /// Creates an instance of `TargetDataLayout`.
-    fn default() -> TargetDataLayout {
-        let align = |bits| Align::from_bits(bits).unwrap();
-        TargetDataLayout {
-            endian: Endian::Big,
-            i1_align: AbiAndPrefAlign::new(align(8)),
-            i8_align: AbiAndPrefAlign::new(align(8)),
-            i16_align: AbiAndPrefAlign::new(align(16)),
-            i32_align: AbiAndPrefAlign::new(align(32)),
-            i64_align: AbiAndPrefAlign { abi: align(32), pref: align(64) },
-            i128_align: AbiAndPrefAlign { abi: align(32), pref: align(64) },
-            f32_align: AbiAndPrefAlign::new(align(32)),
-            f64_align: AbiAndPrefAlign::new(align(64)),
-            pointer_size: Size::from_bits(64),
-            pointer_align: AbiAndPrefAlign::new(align(64)),
-            aggregate_align: AbiAndPrefAlign { abi: align(0), pref: align(64) },
-            vector_align: vec![
-                (Size::from_bits(64), AbiAndPrefAlign::new(align(64))),
-                (Size::from_bits(128), AbiAndPrefAlign::new(align(128))),
-            ],
-            instruction_address_space: AddressSpace::DATA,
-            c_enum_min_size: Integer::I32,
-        }
-    }
-}
-
-pub enum TargetDataLayoutErrors<'a> {
-    InvalidAddressSpace { addr_space: &'a str, cause: &'a str, err: ParseIntError },
-    InvalidBits { kind: &'a str, bit: &'a str, cause: &'a str, err: ParseIntError },
-    MissingAlignment { cause: &'a str },
-    InvalidAlignment { cause: &'a str, err: String },
-    InconsistentTargetArchitecture { dl: &'a str, target: &'a str },
-    InconsistentTargetPointerWidth { pointer_size: u64, target: u32 },
-    InvalidBitsSize { err: String },
-}
-
-impl TargetDataLayout {
-    pub fn parse<'a>(target: &'a Target) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> {
-        // Parse an address space index from a string.
-        let parse_address_space = |s: &'a str, cause: &'a str| {
-            s.parse::<u32>().map(AddressSpace).map_err(|err| {
-                TargetDataLayoutErrors::InvalidAddressSpace { addr_space: s, cause, err }
-            })
-        };
-
-        // Parse a bit count from a string.
-        let parse_bits = |s: &'a str, kind: &'a str, cause: &'a str| {
-            s.parse::<u64>().map_err(|err| TargetDataLayoutErrors::InvalidBits {
-                kind,
-                bit: s,
-                cause,
-                err,
-            })
-        };
-
-        // Parse a size string.
-        let size = |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits);
-
-        // Parse an alignment string.
-        let align = |s: &[&'a str], cause: &'a str| {
-            if s.is_empty() {
-                return Err(TargetDataLayoutErrors::MissingAlignment { cause });
-            }
-            let align_from_bits = |bits| {
-                Align::from_bits(bits)
-                    .map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err })
-            };
-            let abi = parse_bits(s[0], "alignment", cause)?;
-            let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?;
-            Ok(AbiAndPrefAlign { abi: align_from_bits(abi)?, pref: align_from_bits(pref)? })
-        };
-
-        let mut dl = TargetDataLayout::default();
-        let mut i128_align_src = 64;
-        for spec in target.data_layout.split('-') {
-            let spec_parts = spec.split(':').collect::<Vec<_>>();
-
-            match &*spec_parts {
-                ["e"] => dl.endian = Endian::Little,
-                ["E"] => dl.endian = Endian::Big,
-                [p] if p.starts_with('P') => {
-                    dl.instruction_address_space = parse_address_space(&p[1..], "P")?
-                }
-                ["a", ref a @ ..] => dl.aggregate_align = align(a, "a")?,
-                ["f32", ref a @ ..] => dl.f32_align = align(a, "f32")?,
-                ["f64", ref a @ ..] => dl.f64_align = align(a, "f64")?,
-                [p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => {
-                    dl.pointer_size = size(s, p)?;
-                    dl.pointer_align = align(a, p)?;
-                }
-                [s, ref a @ ..] if s.starts_with('i') => {
-                    let Ok(bits) = s[1..].parse::<u64>() else {
-                        size(&s[1..], "i")?; // For the user error.
-                        continue;
-                    };
-                    let a = align(a, s)?;
-                    match bits {
-                        1 => dl.i1_align = a,
-                        8 => dl.i8_align = a,
-                        16 => dl.i16_align = a,
-                        32 => dl.i32_align = a,
-                        64 => dl.i64_align = a,
-                        _ => {}
-                    }
-                    if bits >= i128_align_src && bits <= 128 {
-                        // Default alignment for i128 is decided by taking the alignment of
-                        // largest-sized i{64..=128}.
-                        i128_align_src = bits;
-                        dl.i128_align = a;
-                    }
-                }
-                [s, ref a @ ..] if s.starts_with('v') => {
-                    let v_size = size(&s[1..], "v")?;
-                    let a = align(a, s)?;
-                    if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
-                        v.1 = a;
-                        continue;
-                    }
-                    // No existing entry, add a new one.
-                    dl.vector_align.push((v_size, a));
-                }
-                _ => {} // Ignore everything else.
-            }
-        }
-
-        // Perform consistency checks against the Target information.
-        if dl.endian != target.endian {
-            return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
-                dl: dl.endian.as_str(),
-                target: target.endian.as_str(),
-            });
-        }
-
-        let target_pointer_width: u64 = target.pointer_width.into();
-        if dl.pointer_size.bits() != target_pointer_width {
-            return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
-                pointer_size: dl.pointer_size.bits(),
-                target: target.pointer_width,
-            });
-        }
-
-        dl.c_enum_min_size = match Integer::from_size(Size::from_bits(target.c_enum_min_bits)) {
-            Ok(bits) => bits,
-            Err(err) => return Err(TargetDataLayoutErrors::InvalidBitsSize { err }),
-        };
-
-        Ok(dl)
-    }
-
-    /// Returns exclusive upper bound on object size.
-    ///
-    /// The theoretical maximum object size is defined as the maximum positive `isize` value.
-    /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
-    /// index every address within an object along with one byte past the end, along with allowing
-    /// `isize` to store the difference between any two pointers into an object.
-    ///
-    /// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer
-    /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is
-    /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
-    /// address space on 64-bit ARMv8 and x86_64.
-    #[inline]
-    pub fn obj_size_bound(&self) -> u64 {
-        match self.pointer_size.bits() {
-            16 => 1 << 15,
-            32 => 1 << 31,
-            64 => 1 << 47,
-            bits => panic!("obj_size_bound: unknown pointer bit size {}", bits),
-        }
-    }
-
-    #[inline]
-    pub fn ptr_sized_integer(&self) -> Integer {
-        match self.pointer_size.bits() {
-            16 => I16,
-            32 => I32,
-            64 => I64,
-            bits => panic!("ptr_sized_integer: unknown pointer bit size {}", bits),
-        }
-    }
-
-    #[inline]
-    pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
-        for &(size, align) in &self.vector_align {
-            if size == vec_size {
-                return align;
-            }
-        }
-        // Default to natural alignment, which is what LLVM does.
-        // That is, use the size, rounded up to a power of 2.
-        AbiAndPrefAlign::new(Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap())
-    }
-}
-
-pub trait HasDataLayout {
-    fn data_layout(&self) -> &TargetDataLayout;
-}
-
-impl HasDataLayout for TargetDataLayout {
-    #[inline]
-    fn data_layout(&self) -> &TargetDataLayout {
-        self
-    }
-}
-
-/// Endianness of the target, which must match cfg(target-endian).
-#[derive(Copy, Clone, PartialEq)]
-pub enum Endian {
-    Little,
-    Big,
-}
-
-impl Endian {
-    pub fn as_str(&self) -> &'static str {
-        match self {
-            Self::Little => "little",
-            Self::Big => "big",
-        }
-    }
-}
-
-impl fmt::Debug for Endian {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.write_str(self.as_str())
-    }
-}
-
-impl FromStr for Endian {
-    type Err = String;
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        match s {
-            "little" => Ok(Self::Little),
-            "big" => Ok(Self::Big),
-            _ => Err(format!(r#"unknown endian: "{}""#, s)),
-        }
-    }
-}
+pub use rustc_abi::*;
 
 impl ToJson for Endian {
     fn to_json(&self) -> Json {
@@ -287,1030 +19,15 @@ impl ToJson for Endian {
     }
 }
 
-/// Size of a type in bytes.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
-#[derive(HashStable_Generic)]
-pub struct Size {
-    raw: u64,
-}
-
-// This is debug-printed a lot in larger structs, don't waste too much space there
-impl fmt::Debug for Size {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "Size({} bytes)", self.bytes())
-    }
-}
-
-impl Size {
-    pub const ZERO: Size = Size { raw: 0 };
-
-    /// Rounds `bits` up to the next-higher byte boundary, if `bits` is
-    /// not a multiple of 8.
-    pub fn from_bits(bits: impl TryInto<u64>) -> Size {
-        let bits = bits.try_into().ok().unwrap();
-        // Avoid potential overflow from `bits + 7`.
-        Size { raw: bits / 8 + ((bits % 8) + 7) / 8 }
-    }
-
-    #[inline]
-    pub fn from_bytes(bytes: impl TryInto<u64>) -> Size {
-        let bytes: u64 = bytes.try_into().ok().unwrap();
-        Size { raw: bytes }
-    }
-
-    #[inline]
-    pub fn bytes(self) -> u64 {
-        self.raw
-    }
-
-    #[inline]
-    pub fn bytes_usize(self) -> usize {
-        self.bytes().try_into().unwrap()
-    }
-
-    #[inline]
-    pub fn bits(self) -> u64 {
-        #[cold]
-        fn overflow(bytes: u64) -> ! {
-            panic!("Size::bits: {} bytes in bits doesn't fit in u64", bytes)
-        }
-
-        self.bytes().checked_mul(8).unwrap_or_else(|| overflow(self.bytes()))
-    }
-
-    #[inline]
-    pub fn bits_usize(self) -> usize {
-        self.bits().try_into().unwrap()
-    }
-
-    #[inline]
-    pub fn align_to(self, align: Align) -> Size {
-        let mask = align.bytes() - 1;
-        Size::from_bytes((self.bytes() + mask) & !mask)
-    }
-
-    #[inline]
-    pub fn is_aligned(self, align: Align) -> bool {
-        let mask = align.bytes() - 1;
-        self.bytes() & mask == 0
-    }
-
-    #[inline]
-    pub fn checked_add<C: HasDataLayout>(self, offset: Size, cx: &C) -> Option<Size> {
-        let dl = cx.data_layout();
-
-        let bytes = self.bytes().checked_add(offset.bytes())?;
-
-        if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
-    }
-
-    #[inline]
-    pub fn checked_mul<C: HasDataLayout>(self, count: u64, cx: &C) -> Option<Size> {
-        let dl = cx.data_layout();
-
-        let bytes = self.bytes().checked_mul(count)?;
-        if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
-    }
-
-    /// Truncates `value` to `self` bits and then sign-extends it to 128 bits
-    /// (i.e., if it is negative, fill with 1's on the left).
-    #[inline]
-    pub fn sign_extend(self, value: u128) -> u128 {
-        let size = self.bits();
-        if size == 0 {
-            // Truncated until nothing is left.
-            return 0;
-        }
-        // Sign-extend it.
-        let shift = 128 - size;
-        // Shift the unsigned value to the left, then shift back to the right as signed
-        // (essentially fills with sign bit on the left).
-        (((value << shift) as i128) >> shift) as u128
-    }
-
-    /// Truncates `value` to `self` bits.
-    #[inline]
-    pub fn truncate(self, value: u128) -> u128 {
-        let size = self.bits();
-        if size == 0 {
-            // Truncated until nothing is left.
-            return 0;
-        }
-        let shift = 128 - size;
-        // Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
-        (value << shift) >> shift
-    }
-
-    #[inline]
-    pub fn signed_int_min(&self) -> i128 {
-        self.sign_extend(1_u128 << (self.bits() - 1)) as i128
-    }
-
-    #[inline]
-    pub fn signed_int_max(&self) -> i128 {
-        i128::MAX >> (128 - self.bits())
-    }
-
-    #[inline]
-    pub fn unsigned_int_max(&self) -> u128 {
-        u128::MAX >> (128 - self.bits())
-    }
-}
-
-// Panicking addition, subtraction and multiplication for convenience.
-// Avoid during layout computation, return `LayoutError` instead.
-
-impl Add for Size {
-    type Output = Size;
-    #[inline]
-    fn add(self, other: Size) -> Size {
-        Size::from_bytes(self.bytes().checked_add(other.bytes()).unwrap_or_else(|| {
-            panic!("Size::add: {} + {} doesn't fit in u64", self.bytes(), other.bytes())
-        }))
-    }
-}
-
-impl Sub for Size {
-    type Output = Size;
-    #[inline]
-    fn sub(self, other: Size) -> Size {
-        Size::from_bytes(self.bytes().checked_sub(other.bytes()).unwrap_or_else(|| {
-            panic!("Size::sub: {} - {} would result in negative size", self.bytes(), other.bytes())
-        }))
-    }
-}
-
-impl Mul<Size> for u64 {
-    type Output = Size;
-    #[inline]
-    fn mul(self, size: Size) -> Size {
-        size * self
-    }
-}
-
-impl Mul<u64> for Size {
-    type Output = Size;
-    #[inline]
-    fn mul(self, count: u64) -> Size {
-        match self.bytes().checked_mul(count) {
-            Some(bytes) => Size::from_bytes(bytes),
-            None => panic!("Size::mul: {} * {} doesn't fit in u64", self.bytes(), count),
-        }
-    }
-}
-
-impl AddAssign for Size {
-    #[inline]
-    fn add_assign(&mut self, other: Size) {
-        *self = *self + other;
-    }
-}
-
-impl Step for Size {
-    #[inline]
-    fn steps_between(start: &Self, end: &Self) -> Option<usize> {
-        u64::steps_between(&start.bytes(), &end.bytes())
-    }
-
-    #[inline]
-    fn forward_checked(start: Self, count: usize) -> Option<Self> {
-        u64::forward_checked(start.bytes(), count).map(Self::from_bytes)
-    }
-
-    #[inline]
-    fn forward(start: Self, count: usize) -> Self {
-        Self::from_bytes(u64::forward(start.bytes(), count))
-    }
-
-    #[inline]
-    unsafe fn forward_unchecked(start: Self, count: usize) -> Self {
-        Self::from_bytes(u64::forward_unchecked(start.bytes(), count))
-    }
-
-    #[inline]
-    fn backward_checked(start: Self, count: usize) -> Option<Self> {
-        u64::backward_checked(start.bytes(), count).map(Self::from_bytes)
-    }
-
-    #[inline]
-    fn backward(start: Self, count: usize) -> Self {
-        Self::from_bytes(u64::backward(start.bytes(), count))
-    }
-
-    #[inline]
-    unsafe fn backward_unchecked(start: Self, count: usize) -> Self {
-        Self::from_bytes(u64::backward_unchecked(start.bytes(), count))
-    }
-}
-
-/// Alignment of a type in bytes (always a power of two).
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
-#[derive(HashStable_Generic)]
-pub struct Align {
-    pow2: u8,
-}
-
-// This is debug-printed a lot in larger structs, don't waste too much space there
-impl fmt::Debug for Align {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "Align({} bytes)", self.bytes())
-    }
-}
-
-impl Align {
-    pub const ONE: Align = Align { pow2: 0 };
-    pub const MAX: Align = Align { pow2: 29 };
-
-    #[inline]
-    pub fn from_bits(bits: u64) -> Result<Align, String> {
-        Align::from_bytes(Size::from_bits(bits).bytes())
-    }
-
-    #[inline]
-    pub fn from_bytes(align: u64) -> Result<Align, String> {
-        // Treat an alignment of 0 bytes like 1-byte alignment.
-        if align == 0 {
-            return Ok(Align::ONE);
-        }
-
-        #[cold]
-        fn not_power_of_2(align: u64) -> String {
-            format!("`{}` is not a power of 2", align)
-        }
-
-        #[cold]
-        fn too_large(align: u64) -> String {
-            format!("`{}` is too large", align)
-        }
-
-        let mut bytes = align;
-        let mut pow2: u8 = 0;
-        while (bytes & 1) == 0 {
-            pow2 += 1;
-            bytes >>= 1;
-        }
-        if bytes != 1 {
-            return Err(not_power_of_2(align));
-        }
-        if pow2 > Self::MAX.pow2 {
-            return Err(too_large(align));
-        }
-
-        Ok(Align { pow2 })
-    }
-
-    #[inline]
-    pub fn bytes(self) -> u64 {
-        1 << self.pow2
-    }
-
-    #[inline]
-    pub fn bits(self) -> u64 {
-        self.bytes() * 8
-    }
-
-    /// Computes the best alignment possible for the given offset
-    /// (the largest power of two that the offset is a multiple of).
-    ///
-    /// N.B., for an offset of `0`, this happens to return `2^64`.
-    #[inline]
-    pub fn max_for_offset(offset: Size) -> Align {
-        Align { pow2: offset.bytes().trailing_zeros() as u8 }
-    }
-
-    /// Lower the alignment, if necessary, such that the given offset
-    /// is aligned to it (the offset is a multiple of the alignment).
-    #[inline]
-    pub fn restrict_for_offset(self, offset: Size) -> Align {
-        self.min(Align::max_for_offset(offset))
-    }
-}
-
-/// A pair of alignments, ABI-mandated and preferred.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-#[derive(HashStable_Generic)]
-pub struct AbiAndPrefAlign {
-    pub abi: Align,
-    pub pref: Align,
-}
-
-impl AbiAndPrefAlign {
-    #[inline]
-    pub fn new(align: Align) -> AbiAndPrefAlign {
-        AbiAndPrefAlign { abi: align, pref: align }
-    }
-
-    #[inline]
-    pub fn min(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
-        AbiAndPrefAlign { abi: self.abi.min(other.abi), pref: self.pref.min(other.pref) }
-    }
-
-    #[inline]
-    pub fn max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
-        AbiAndPrefAlign { abi: self.abi.max(other.abi), pref: self.pref.max(other.pref) }
-    }
-}
-
-/// Integers, also used for enum discriminants.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, HashStable_Generic)]
-pub enum Integer {
-    I8,
-    I16,
-    I32,
-    I64,
-    I128,
-}
-
-impl Integer {
-    #[inline]
-    pub fn size(self) -> Size {
-        match self {
-            I8 => Size::from_bytes(1),
-            I16 => Size::from_bytes(2),
-            I32 => Size::from_bytes(4),
-            I64 => Size::from_bytes(8),
-            I128 => Size::from_bytes(16),
-        }
-    }
-
-    pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
-        let dl = cx.data_layout();
-
-        match self {
-            I8 => dl.i8_align,
-            I16 => dl.i16_align,
-            I32 => dl.i32_align,
-            I64 => dl.i64_align,
-            I128 => dl.i128_align,
-        }
-    }
-
-    /// Finds the smallest Integer type which can represent the signed value.
-    #[inline]
-    pub fn fit_signed(x: i128) -> Integer {
-        match x {
-            -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8,
-            -0x0000_0000_0000_8000..=0x0000_0000_0000_7fff => I16,
-            -0x0000_0000_8000_0000..=0x0000_0000_7fff_ffff => I32,
-            -0x8000_0000_0000_0000..=0x7fff_ffff_ffff_ffff => I64,
-            _ => I128,
-        }
-    }
-
-    /// Finds the smallest Integer type which can represent the unsigned value.
-    #[inline]
-    pub fn fit_unsigned(x: u128) -> Integer {
-        match x {
-            0..=0x0000_0000_0000_00ff => I8,
-            0..=0x0000_0000_0000_ffff => I16,
-            0..=0x0000_0000_ffff_ffff => I32,
-            0..=0xffff_ffff_ffff_ffff => I64,
-            _ => I128,
-        }
-    }
-
-    /// Finds the smallest integer with the given alignment.
-    pub fn for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer> {
-        let dl = cx.data_layout();
-
-        for candidate in [I8, I16, I32, I64, I128] {
-            if wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() {
-                return Some(candidate);
-            }
-        }
-        None
-    }
-
-    /// Find the largest integer with the given alignment or less.
-    pub fn approximate_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Integer {
-        let dl = cx.data_layout();
-
-        // FIXME(eddyb) maybe include I128 in the future, when it works everywhere.
-        for candidate in [I64, I32, I16] {
-            if wanted >= candidate.align(dl).abi && wanted.bytes() >= candidate.size().bytes() {
-                return candidate;
-            }
-        }
-        I8
-    }
-
-    // FIXME(eddyb) consolidate this and other methods that find the appropriate
-    // `Integer` given some requirements.
-    #[inline]
-    fn from_size(size: Size) -> Result<Self, String> {
-        match size.bits() {
-            8 => Ok(Integer::I8),
-            16 => Ok(Integer::I16),
-            32 => Ok(Integer::I32),
-            64 => Ok(Integer::I64),
-            128 => Ok(Integer::I128),
-            _ => Err(format!("rust does not support integers with {} bits", size.bits())),
-        }
-    }
-}
-
-/// Fundamental unit of memory access and layout.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub enum Primitive {
-    /// The `bool` is the signedness of the `Integer` type.
-    ///
-    /// One would think we would not care about such details this low down,
-    /// but some ABIs are described in terms of C types and ISAs where the
-    /// integer arithmetic is done on {sign,zero}-extended registers, e.g.
-    /// a negative integer passed by zero-extension will appear positive in
-    /// the callee, and most operations on it will produce the wrong values.
-    Int(Integer, bool),
-    F32,
-    F64,
-    Pointer,
-}
-
-impl Primitive {
-    pub fn size<C: HasDataLayout>(self, cx: &C) -> Size {
-        let dl = cx.data_layout();
-
-        match self {
-            Int(i, _) => i.size(),
-            F32 => Size::from_bits(32),
-            F64 => Size::from_bits(64),
-            Pointer => dl.pointer_size,
-        }
-    }
-
-    pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
-        let dl = cx.data_layout();
-
-        match self {
-            Int(i, _) => i.align(dl),
-            F32 => dl.f32_align,
-            F64 => dl.f64_align,
-            Pointer => dl.pointer_align,
-        }
-    }
-
-    // FIXME(eddyb) remove, it's trivial thanks to `matches!`.
-    #[inline]
-    pub fn is_float(self) -> bool {
-        matches!(self, F32 | F64)
-    }
-
-    // FIXME(eddyb) remove, it's completely unused.
-    #[inline]
-    pub fn is_int(self) -> bool {
-        matches!(self, Int(..))
-    }
-
-    #[inline]
-    pub fn is_ptr(self) -> bool {
-        matches!(self, Pointer)
-    }
-}
-
-/// Inclusive wrap-around range of valid values, that is, if
-/// start > end, it represents `start..=MAX`,
-/// followed by `0..=end`.
-///
-/// That is, for an i8 primitive, a range of `254..=2` means following
-/// sequence:
-///
-///    254 (-2), 255 (-1), 0, 1, 2
-///
-/// This is intended specifically to mirror LLVM’s `!range` metadata semantics.
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-#[derive(HashStable_Generic)]
-pub struct WrappingRange {
-    pub start: u128,
-    pub end: u128,
-}
-
-impl WrappingRange {
-    pub fn full(size: Size) -> Self {
-        Self { start: 0, end: size.unsigned_int_max() }
-    }
-
-    /// Returns `true` if `v` is contained in the range.
-    #[inline(always)]
-    pub fn contains(&self, v: u128) -> bool {
-        if self.start <= self.end {
-            self.start <= v && v <= self.end
-        } else {
-            self.start <= v || v <= self.end
-        }
-    }
-
-    /// Returns `self` with replaced `start`
-    #[inline(always)]
-    pub fn with_start(mut self, start: u128) -> Self {
-        self.start = start;
-        self
-    }
-
-    /// Returns `self` with replaced `end`
-    #[inline(always)]
-    pub fn with_end(mut self, end: u128) -> Self {
-        self.end = end;
-        self
-    }
-
-    /// Returns `true` if `size` completely fills the range.
-    #[inline]
-    pub fn is_full_for(&self, size: Size) -> bool {
-        let max_value = size.unsigned_int_max();
-        debug_assert!(self.start <= max_value && self.end <= max_value);
-        self.start == (self.end.wrapping_add(1) & max_value)
-    }
-}
-
-impl fmt::Debug for WrappingRange {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if self.start > self.end {
-            write!(fmt, "(..={}) | ({}..)", self.end, self.start)?;
-        } else {
-            write!(fmt, "{}..={}", self.start, self.end)?;
-        }
-        Ok(())
-    }
-}
-
-/// Information about one scalar component of a Rust type.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
-#[derive(HashStable_Generic)]
-pub enum Scalar {
-    Initialized {
-        value: Primitive,
-
-        // FIXME(eddyb) always use the shortest range, e.g., by finding
-        // the largest space between two consecutive valid values and
-        // taking everything else as the (shortest) valid range.
-        valid_range: WrappingRange,
-    },
-    Union {
-        /// Even for unions, we need to use the correct registers for the kind of
-        /// values inside the union, so we keep the `Primitive` type around. We
-        /// also use it to compute the size of the scalar.
-        /// However, unions never have niches and even allow undef,
-        /// so there is no `valid_range`.
-        value: Primitive,
-    },
-}
-
-impl Scalar {
-    #[inline]
-    pub fn is_bool(&self) -> bool {
-        matches!(
-            self,
-            Scalar::Initialized {
-                value: Int(I8, false),
-                valid_range: WrappingRange { start: 0, end: 1 }
-            }
-        )
-    }
-
-    /// Get the primitive representation of this type, ignoring the valid range and whether the
-    /// value is allowed to be undefined (due to being a union).
-    pub fn primitive(&self) -> Primitive {
-        match *self {
-            Scalar::Initialized { value, .. } | Scalar::Union { value } => value,
-        }
-    }
-
-    pub fn align(self, cx: &impl HasDataLayout) -> AbiAndPrefAlign {
-        self.primitive().align(cx)
-    }
-
-    pub fn size(self, cx: &impl HasDataLayout) -> Size {
-        self.primitive().size(cx)
-    }
-
-    #[inline]
-    pub fn to_union(&self) -> Self {
-        Self::Union { value: self.primitive() }
-    }
-
-    #[inline]
-    pub fn valid_range(&self, cx: &impl HasDataLayout) -> WrappingRange {
-        match *self {
-            Scalar::Initialized { valid_range, .. } => valid_range,
-            Scalar::Union { value } => WrappingRange::full(value.size(cx)),
-        }
-    }
-
-    #[inline]
-    /// Allows the caller to mutate the valid range. This operation will panic if attempted on a union.
-    pub fn valid_range_mut(&mut self) -> &mut WrappingRange {
-        match self {
-            Scalar::Initialized { valid_range, .. } => valid_range,
-            Scalar::Union { .. } => panic!("cannot change the valid range of a union"),
-        }
-    }
-
-    /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout
-    #[inline]
-    pub fn is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool {
-        match *self {
-            Scalar::Initialized { valid_range, .. } => valid_range.is_full_for(self.size(cx)),
-            Scalar::Union { .. } => true,
-        }
-    }
-
-    /// Returns `true` if this type can be left uninit.
-    #[inline]
-    pub fn is_uninit_valid(&self) -> bool {
-        match *self {
-            Scalar::Initialized { .. } => false,
-            Scalar::Union { .. } => true,
-        }
-    }
-}
-
-/// Describes how the fields of a type are located in memory.
-#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub enum FieldsShape {
-    /// Scalar primitives and `!`, which never have fields.
-    Primitive,
-
-    /// All fields start at no offset. The `usize` is the field count.
-    Union(NonZeroUsize),
-
-    /// Array/vector-like placement, with all fields of identical types.
-    Array { stride: Size, count: u64 },
-
-    /// Struct-like placement, with precomputed offsets.
-    ///
-    /// Fields are guaranteed to not overlap, but note that gaps
-    /// before, between and after all the fields are NOT always
-    /// padding, and as such their contents may not be discarded.
-    /// For example, enum variants leave a gap at the start,
-    /// where the discriminant field in the enum layout goes.
-    Arbitrary {
-        /// Offsets for the first byte of each field,
-        /// ordered to match the source definition order.
-        /// This vector does not go in increasing order.
-        // FIXME(eddyb) use small vector optimization for the common case.
-        offsets: Vec<Size>,
-
-        /// Maps source order field indices to memory order indices,
-        /// depending on how the fields were reordered (if at all).
-        /// This is a permutation, with both the source order and the
-        /// memory order using the same (0..n) index ranges.
-        ///
-        /// Note that during computation of `memory_index`, sometimes
-        /// it is easier to operate on the inverse mapping (that is,
-        /// from memory order to source order), and that is usually
-        /// named `inverse_memory_index`.
-        ///
-        // FIXME(eddyb) build a better abstraction for permutations, if possible.
-        // FIXME(camlorn) also consider small vector  optimization here.
-        memory_index: Vec<u32>,
-    },
-}
-
-impl FieldsShape {
-    #[inline]
-    pub fn count(&self) -> usize {
-        match *self {
-            FieldsShape::Primitive => 0,
-            FieldsShape::Union(count) => count.get(),
-            FieldsShape::Array { count, .. } => count.try_into().unwrap(),
-            FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(),
-        }
-    }
-
-    #[inline]
-    pub fn offset(&self, i: usize) -> Size {
-        match *self {
-            FieldsShape::Primitive => {
-                unreachable!("FieldsShape::offset: `Primitive`s have no fields")
-            }
-            FieldsShape::Union(count) => {
-                assert!(
-                    i < count.get(),
-                    "tried to access field {} of union with {} fields",
-                    i,
-                    count
-                );
-                Size::ZERO
-            }
-            FieldsShape::Array { stride, count } => {
-                let i = u64::try_from(i).unwrap();
-                assert!(i < count);
-                stride * i
-            }
-            FieldsShape::Arbitrary { ref offsets, .. } => offsets[i],
-        }
-    }
-
-    #[inline]
-    pub fn memory_index(&self, i: usize) -> usize {
-        match *self {
-            FieldsShape::Primitive => {
-                unreachable!("FieldsShape::memory_index: `Primitive`s have no fields")
-            }
-            FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
-            FieldsShape::Arbitrary { ref memory_index, .. } => memory_index[i].try_into().unwrap(),
-        }
-    }
-
-    /// Gets source indices of the fields by increasing offsets.
-    #[inline]
-    pub fn index_by_increasing_offset<'a>(&'a self) -> impl Iterator<Item = usize> + 'a {
-        let mut inverse_small = [0u8; 64];
-        let mut inverse_big = vec![];
-        let use_small = self.count() <= inverse_small.len();
-
-        // We have to write this logic twice in order to keep the array small.
-        if let FieldsShape::Arbitrary { ref memory_index, .. } = *self {
-            if use_small {
-                for i in 0..self.count() {
-                    inverse_small[memory_index[i] as usize] = i as u8;
-                }
-            } else {
-                inverse_big = vec![0; self.count()];
-                for i in 0..self.count() {
-                    inverse_big[memory_index[i] as usize] = i as u32;
-                }
-            }
-        }
-
-        (0..self.count()).map(move |i| match *self {
-            FieldsShape::Primitive | FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
-            FieldsShape::Arbitrary { .. } => {
-                if use_small {
-                    inverse_small[i] as usize
-                } else {
-                    inverse_big[i] as usize
-                }
-            }
-        })
-    }
-}
-
-/// An identifier that specifies the address space that some operation
-/// should operate on. Special address spaces have an effect on code generation,
-/// depending on the target and the address spaces it implements.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-pub struct AddressSpace(pub u32);
-
-impl AddressSpace {
-    /// The default address space, corresponding to data space.
-    pub const DATA: Self = AddressSpace(0);
-}
-
-/// Describes how values of the type are passed by target ABIs,
-/// in terms of categories of C types there are ABI rules for.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub enum Abi {
-    Uninhabited,
-    Scalar(Scalar),
-    ScalarPair(Scalar, Scalar),
-    Vector {
-        element: Scalar,
-        count: u64,
-    },
-    Aggregate {
-        /// If true, the size is exact, otherwise it's only a lower bound.
-        sized: bool,
-    },
-}
-
-impl Abi {
-    /// Returns `true` if the layout corresponds to an unsized type.
-    #[inline]
-    pub fn is_unsized(&self) -> bool {
-        match *self {
-            Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
-            Abi::Aggregate { sized } => !sized,
-        }
-    }
-
-    #[inline]
-    pub fn is_sized(&self) -> bool {
-        !self.is_unsized()
-    }
-
-    /// Returns `true` if this is a single signed integer scalar
-    #[inline]
-    pub fn is_signed(&self) -> bool {
-        match self {
-            Abi::Scalar(scal) => match scal.primitive() {
-                Primitive::Int(_, signed) => signed,
-                _ => false,
-            },
-            _ => panic!("`is_signed` on non-scalar ABI {:?}", self),
-        }
-    }
-
-    /// Returns `true` if this is an uninhabited type
-    #[inline]
-    pub fn is_uninhabited(&self) -> bool {
-        matches!(*self, Abi::Uninhabited)
-    }
-
-    /// Returns `true` is this is a scalar type
-    #[inline]
-    pub fn is_scalar(&self) -> bool {
-        matches!(*self, Abi::Scalar(_))
-    }
-}
-
 rustc_index::newtype_index! {
     pub struct VariantIdx {
         derive [HashStable_Generic]
     }
 }
 
-#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub enum Variants<'a> {
-    /// Single enum variants, structs/tuples, unions, and all non-ADTs.
-    Single { index: VariantIdx },
-
-    /// Enum-likes with more than one inhabited variant: each variant comes with
-    /// a *discriminant* (usually the same as the variant index but the user can
-    /// assign explicit discriminant values).  That discriminant is encoded
-    /// as a *tag* on the machine.  The layout of each variant is
-    /// a struct, and they all have space reserved for the tag.
-    /// For enums, the tag is the sole field of the layout.
-    Multiple {
-        tag: Scalar,
-        tag_encoding: TagEncoding,
-        tag_field: usize,
-        variants: IndexVec<VariantIdx, Layout<'a>>,
-    },
-}
-
-#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub enum TagEncoding {
-    /// The tag directly stores the discriminant, but possibly with a smaller layout
-    /// (so converting the tag to the discriminant can require sign extension).
-    Direct,
-
-    /// Niche (values invalid for a type) encoding the discriminant:
-    /// Discriminant and variant index coincide.
-    /// The variant `untagged_variant` contains a niche at an arbitrary
-    /// offset (field `tag_field` of the enum), which for a variant with
-    /// discriminant `d` is set to
-    /// `(d - niche_variants.start).wrapping_add(niche_start)`.
-    ///
-    /// For example, `Option<(usize, &T)>`  is represented such that
-    /// `None` has a null pointer for the second tuple field, and
-    /// `Some` is the identity function (with a non-null reference).
-    Niche {
-        untagged_variant: VariantIdx,
-        niche_variants: RangeInclusive<VariantIdx>,
-        niche_start: u128,
-    },
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub struct Niche {
-    pub offset: Size,
-    pub value: Primitive,
-    pub valid_range: WrappingRange,
-}
-
-impl Niche {
-    pub fn from_scalar<C: HasDataLayout>(cx: &C, offset: Size, scalar: Scalar) -> Option<Self> {
-        let Scalar::Initialized { value, valid_range } = scalar else { return None };
-        let niche = Niche { offset, value, valid_range };
-        if niche.available(cx) > 0 { Some(niche) } else { None }
-    }
-
-    pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
-        let Self { value, valid_range: v, .. } = *self;
-        let size = value.size(cx);
-        assert!(size.bits() <= 128);
-        let max_value = size.unsigned_int_max();
-
-        // Find out how many values are outside the valid range.
-        let niche = v.end.wrapping_add(1)..v.start;
-        niche.end.wrapping_sub(niche.start) & max_value
-    }
-
-    pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
-        assert!(count > 0);
-
-        let Self { value, valid_range: v, .. } = *self;
-        let size = value.size(cx);
-        assert!(size.bits() <= 128);
-        let max_value = size.unsigned_int_max();
-
-        let niche = v.end.wrapping_add(1)..v.start;
-        let available = niche.end.wrapping_sub(niche.start) & max_value;
-        if count > available {
-            return None;
-        }
-
-        // Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound.
-        // Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy the niche of zero.
-        // This is accomplished by preferring enums with 2 variants(`count==1`) and always taking the shortest path to niche zero.
-        // Having `None` in niche zero can enable some special optimizations.
-        //
-        // Bound selection criteria:
-        // 1. Select closest to zero given wrapping semantics.
-        // 2. Avoid moving past zero if possible.
-        //
-        // In practice this means that enums with `count > 1` are unlikely to claim niche zero, since they have to fit perfectly.
-        // If niche zero is already reserved, the selection of bounds are of little interest.
-        let move_start = |v: WrappingRange| {
-            let start = v.start.wrapping_sub(count) & max_value;
-            Some((start, Scalar::Initialized { value, valid_range: v.with_start(start) }))
-        };
-        let move_end = |v: WrappingRange| {
-            let start = v.end.wrapping_add(1) & max_value;
-            let end = v.end.wrapping_add(count) & max_value;
-            Some((start, Scalar::Initialized { value, valid_range: v.with_end(end) }))
-        };
-        let distance_end_zero = max_value - v.end;
-        if v.start > v.end {
-            // zero is unavailable because wrapping occurs
-            move_end(v)
-        } else if v.start <= distance_end_zero {
-            if count <= v.start {
-                move_start(v)
-            } else {
-                // moved past zero, use other bound
-                move_end(v)
-            }
-        } else {
-            let end = v.end.wrapping_add(count) & max_value;
-            let overshot_zero = (1..=v.end).contains(&end);
-            if overshot_zero {
-                // moved past zero, use other bound
-                move_start(v)
-            } else {
-                move_end(v)
-            }
-        }
-    }
-}
-
-#[derive(PartialEq, Eq, Hash, HashStable_Generic)]
-pub struct LayoutS<'a> {
-    /// Says where the fields are located within the layout.
-    pub fields: FieldsShape,
-
-    /// Encodes information about multi-variant layouts.
-    /// Even with `Multiple` variants, a layout still has its own fields! Those are then
-    /// shared between all variants. One of them will be the discriminant,
-    /// but e.g. generators can have more.
-    ///
-    /// To access all fields of this layout, both `fields` and the fields of the active variant
-    /// must be taken into account.
-    pub variants: Variants<'a>,
-
-    /// The `abi` defines how this data is passed between functions, and it defines
-    /// value restrictions via `valid_range`.
-    ///
-    /// Note that this is entirely orthogonal to the recursive structure defined by
-    /// `variants` and `fields`; for example, `ManuallyDrop<Result<isize, isize>>` has
-    /// `Abi::ScalarPair`! So, even with non-`Aggregate` `abi`, `fields` and `variants`
-    /// have to be taken into account to find all fields of this layout.
-    pub abi: Abi,
-
-    /// The leaf scalar with the largest number of invalid values
-    /// (i.e. outside of its `valid_range`), if it exists.
-    pub largest_niche: Option<Niche>,
-
-    pub align: AbiAndPrefAlign,
-    pub size: Size,
-}
-
-impl<'a> LayoutS<'a> {
-    pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
-        let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
-        let size = scalar.size(cx);
-        let align = scalar.align(cx);
-        LayoutS {
-            variants: Variants::Single { index: VariantIdx::new(0) },
-            fields: FieldsShape::Primitive,
-            abi: Abi::Scalar(scalar),
-            largest_niche,
-            size,
-            align,
-        }
-    }
-}
-
-impl<'a> fmt::Debug for LayoutS<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // This is how `Layout` used to print before it become
-        // `Interned<LayoutS>`. We print it like this to avoid having to update
-        // expected output in a lot of tests.
-        let LayoutS { size, align, abi, fields, largest_niche, variants } = self;
-        f.debug_struct("Layout")
-            .field("size", size)
-            .field("align", align)
-            .field("abi", abi)
-            .field("fields", fields)
-            .field("largest_niche", largest_niche)
-            .field("variants", variants)
-            .finish()
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
 #[rustc_pass_by_value]
-pub struct Layout<'a>(pub Interned<'a, LayoutS<'a>>);
+pub struct Layout<'a>(pub Interned<'a, LayoutS<VariantIdx>>);
 
 impl<'a> fmt::Debug for Layout<'a> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -1324,7 +41,7 @@ impl<'a> Layout<'a> {
         &self.0.0.fields
     }
 
-    pub fn variants(self) -> &'a Variants<'a> {
+    pub fn variants(self) -> &'a Variants<VariantIdx> {
         &self.0.0.variants
     }
 
@@ -1359,47 +76,12 @@ pub struct TyAndLayout<'a, Ty> {
 }
 
 impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
-    type Target = &'a LayoutS<'a>;
-    fn deref(&self) -> &&'a LayoutS<'a> {
+    type Target = &'a LayoutS<VariantIdx>;
+    fn deref(&self) -> &&'a LayoutS<VariantIdx> {
         &self.layout.0.0
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum PointerKind {
-    /// Most general case, we know no restrictions to tell LLVM.
-    SharedMutable,
-
-    /// `&T` where `T` contains no `UnsafeCell`, is `dereferenceable`, `noalias` and `readonly`.
-    Frozen,
-
-    /// `&mut T` which is `dereferenceable` and `noalias` but not `readonly`.
-    UniqueBorrowed,
-
-    /// `&mut !Unpin`, which is `dereferenceable` but neither `noalias` nor `readonly`.
-    UniqueBorrowedPinned,
-
-    /// `Box<T>`, which is `noalias` (even on return types, unlike the above) but neither `readonly`
-    /// nor `dereferenceable`.
-    UniqueOwned,
-}
-
-#[derive(Copy, Clone, Debug)]
-pub struct PointeeInfo {
-    pub size: Size,
-    pub align: Align,
-    pub safe: Option<PointerKind>,
-    pub address_space: AddressSpace,
-}
-
-/// Used in `might_permit_raw_init` to indicate the kind of initialisation
-/// that is checked to be valid
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum InitKind {
-    Zero,
-    UninitMitigated0x01Fill,
-}
-
 /// Trait that needs to be implemented by the higher-level type representation
 /// (e.g. `rustc_middle::ty::Ty`), to provide `rustc_target::abi` functionality.
 pub trait TyAbiInterface<'a, C>: Sized {
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index aaba0d7f093..b69a0a645a4 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -35,10 +35,7 @@ pub mod spec;
 #[cfg(test)]
 mod tests;
 
-/// Requirements for a `StableHashingContext` to be used in this crate.
-/// This is a hack to allow using the `HashStable_Generic` derive macro
-/// instead of implementing everything in `rustc_middle`.
-pub trait HashStableContext {}
+pub use rustc_abi::HashStableContext;
 
 /// The name of rustc's own place to organize libraries.
 ///
diff --git a/compiler/rustc_target/src/spec/aix_base.rs b/compiler/rustc_target/src/spec/aix_base.rs
new file mode 100644
index 00000000000..c71c4ba2cc9
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aix_base.rs
@@ -0,0 +1,32 @@
+use crate::abi::Endian;
+use crate::spec::{crt_objects, cvs, Cc, CodeModel, LinkOutputKind, LinkerFlavor, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+    TargetOptions {
+        abi: "vec-extabi".into(),
+        code_model: Some(CodeModel::Small),
+        cpu: "pwr7".into(),
+        os: "aix".into(),
+        vendor: "ibm".into(),
+        dynamic_linking: true,
+        endian: Endian::Big,
+        executables: true,
+        archive_format: "aix_big".into(),
+        families: cvs!["unix"],
+        has_rpath: false,
+        has_thread_local: true,
+        crt_static_respected: true,
+        linker_flavor: LinkerFlavor::Unix(Cc::No),
+        linker: Some("ld".into()),
+        eh_frame_header: false,
+        is_like_aix: true,
+        default_dwarf_version: 3,
+        function_sections: true,
+        pre_link_objects: crt_objects::new(&[
+            (LinkOutputKind::DynamicNoPicExe, &["/usr/lib/crt0_64.o", "/usr/lib/crti_64.o"]),
+            (LinkOutputKind::DynamicPicExe, &["/usr/lib/crt0_64.o", "/usr/lib/crti_64.o"]),
+        ]),
+        dll_suffix: ".a".into(),
+        ..Default::default()
+    }
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 6d936d2cb9f..bd5b10d6aa7 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -35,7 +35,10 @@
 //! to the list specified by the target, rather than replace.
 
 use crate::abi::call::Conv;
-use crate::abi::Endian;
+use crate::abi::{
+    AbiAndPrefAlign, AddressSpace, Align, Endian, Integer, Size, TargetDataLayout,
+    TargetDataLayoutErrors,
+};
 use crate::json::{Json, ToJson};
 use crate::spec::abi::{lookup as lookup_abi, Abi};
 use crate::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
@@ -58,6 +61,7 @@ use rustc_macros::HashStable_Generic;
 pub mod abi;
 pub mod crt_objects;
 
+mod aix_base;
 mod android_base;
 mod apple_base;
 mod avr_gnu_base;
@@ -1027,6 +1031,7 @@ supported_targets! {
     ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
     ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
     ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
+    ("powerpc64-ibm-aix", powerpc64_ibm_aix),
     ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
     ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
     ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
@@ -1315,6 +1320,120 @@ pub struct Target {
     pub options: TargetOptions,
 }
 
+impl Target {
+    pub fn parse_data_layout<'a>(&'a self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> {
+        // Parse an address space index from a string.
+        let parse_address_space = |s: &'a str, cause: &'a str| {
+            s.parse::<u32>().map(AddressSpace).map_err(|err| {
+                TargetDataLayoutErrors::InvalidAddressSpace { addr_space: s, cause, err }
+            })
+        };
+
+        // Parse a bit count from a string.
+        let parse_bits = |s: &'a str, kind: &'a str, cause: &'a str| {
+            s.parse::<u64>().map_err(|err| TargetDataLayoutErrors::InvalidBits {
+                kind,
+                bit: s,
+                cause,
+                err,
+            })
+        };
+
+        // Parse a size string.
+        let size = |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits);
+
+        // Parse an alignment string.
+        let align = |s: &[&'a str], cause: &'a str| {
+            if s.is_empty() {
+                return Err(TargetDataLayoutErrors::MissingAlignment { cause });
+            }
+            let align_from_bits = |bits| {
+                Align::from_bits(bits)
+                    .map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err })
+            };
+            let abi = parse_bits(s[0], "alignment", cause)?;
+            let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?;
+            Ok(AbiAndPrefAlign { abi: align_from_bits(abi)?, pref: align_from_bits(pref)? })
+        };
+
+        let mut dl = TargetDataLayout::default();
+        let mut i128_align_src = 64;
+        for spec in self.data_layout.split('-') {
+            let spec_parts = spec.split(':').collect::<Vec<_>>();
+
+            match &*spec_parts {
+                ["e"] => dl.endian = Endian::Little,
+                ["E"] => dl.endian = Endian::Big,
+                [p] if p.starts_with('P') => {
+                    dl.instruction_address_space = parse_address_space(&p[1..], "P")?
+                }
+                ["a", ref a @ ..] => dl.aggregate_align = align(a, "a")?,
+                ["f32", ref a @ ..] => dl.f32_align = align(a, "f32")?,
+                ["f64", ref a @ ..] => dl.f64_align = align(a, "f64")?,
+                [p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => {
+                    dl.pointer_size = size(s, p)?;
+                    dl.pointer_align = align(a, p)?;
+                }
+                [s, ref a @ ..] if s.starts_with('i') => {
+                    let Ok(bits) = s[1..].parse::<u64>() else {
+                        size(&s[1..], "i")?; // For the user error.
+                        continue;
+                    };
+                    let a = align(a, s)?;
+                    match bits {
+                        1 => dl.i1_align = a,
+                        8 => dl.i8_align = a,
+                        16 => dl.i16_align = a,
+                        32 => dl.i32_align = a,
+                        64 => dl.i64_align = a,
+                        _ => {}
+                    }
+                    if bits >= i128_align_src && bits <= 128 {
+                        // Default alignment for i128 is decided by taking the alignment of
+                        // largest-sized i{64..=128}.
+                        i128_align_src = bits;
+                        dl.i128_align = a;
+                    }
+                }
+                [s, ref a @ ..] if s.starts_with('v') => {
+                    let v_size = size(&s[1..], "v")?;
+                    let a = align(a, s)?;
+                    if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
+                        v.1 = a;
+                        continue;
+                    }
+                    // No existing entry, add a new one.
+                    dl.vector_align.push((v_size, a));
+                }
+                _ => {} // Ignore everything else.
+            }
+        }
+
+        // Perform consistency checks against the Target information.
+        if dl.endian != self.endian {
+            return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
+                dl: dl.endian.as_str(),
+                target: self.endian.as_str(),
+            });
+        }
+
+        let target_pointer_width: u64 = self.pointer_width.into();
+        if dl.pointer_size.bits() != target_pointer_width {
+            return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
+                pointer_size: dl.pointer_size.bits(),
+                target: self.pointer_width,
+            });
+        }
+
+        dl.c_enum_min_size = match Integer::from_size(Size::from_bits(self.c_enum_min_bits)) {
+            Ok(bits) => bits,
+            Err(err) => return Err(TargetDataLayoutErrors::InvalidBitsSize { err }),
+        };
+
+        Ok(dl)
+    }
+}
+
 pub trait HasTargetSpec {
     fn target_spec(&self) -> &Target;
 }
@@ -1454,6 +1573,9 @@ pub struct TargetOptions {
     pub families: StaticCow<[StaticCow<str>]>,
     /// Whether the target toolchain's ABI supports returning small structs as an integer.
     pub abi_return_struct_as_int: bool,
+    /// Whether the target toolchain is like AIX's. Linker options on AIX are special and it uses
+    /// XCOFF as binary format. Defaults to false.
+    pub is_like_aix: bool,
     /// Whether the target toolchain is like macOS's. Only useful for compiling against iOS/macOS,
     /// in particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false.
     /// Also indiates whether to use Apple-specific ABI changes, such as extending function
@@ -1817,6 +1939,7 @@ impl Default for TargetOptions {
             staticlib_suffix: ".a".into(),
             families: cvs![],
             abi_return_struct_as_int: false,
+            is_like_aix: false,
             is_like_osx: false,
             is_like_solaris: false,
             is_like_windows: false,
@@ -2488,6 +2611,7 @@ impl Target {
         key!(staticlib_suffix);
         key!(families, TargetFamilies);
         key!(abi_return_struct_as_int, bool);
+        key!(is_like_aix, bool);
         key!(is_like_osx, bool);
         key!(is_like_solaris, bool);
         key!(is_like_windows, bool);
@@ -2741,6 +2865,7 @@ impl ToJson for Target {
         target_option_val!(staticlib_suffix);
         target_option_val!(families, "target-family");
         target_option_val!(abi_return_struct_as_int);
+        target_option_val!(is_like_aix);
         target_option_val!(is_like_osx);
         target_option_val!(is_like_solaris);
         target_option_val!(is_like_windows);
diff --git a/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs b/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs
new file mode 100644
index 00000000000..e3eb9bccd5e
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs
@@ -0,0 +1,23 @@
+use crate::spec::{Cc, LinkerFlavor, Target};
+
+pub fn target() -> Target {
+    let mut base = super::aix_base::opts();
+    base.max_atomic_width = Some(64);
+    base.add_pre_link_args(
+        LinkerFlavor::Unix(Cc::No),
+        &[
+            "-b64".into(),
+            "-bpT:0x100000000".into(),
+            "-bpD:0x110000000".into(),
+            "-bcdtors:all:0:s".into(),
+        ],
+    );
+
+    Target {
+        llvm_target: "powerpc64-ibm-aix".into(),
+        pointer_width: 64,
+        data_layout: "E-m:a-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
+        arch: "powerpc64".into(),
+        options: base,
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs
index 9b39a940114..1102f44a82e 100644
--- a/compiler/rustc_trait_selection/src/autoderef.rs
+++ b/compiler/rustc_trait_selection/src/autoderef.rs
@@ -1,4 +1,5 @@
 use crate::errors::AutoDerefReachedRecursionLimit;
+use crate::infer::InferCtxtExt as _;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::{self, TraitEngine, TraitEngineExt};
 use rustc_hir as hir;
@@ -137,16 +138,14 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
             return None;
         }
 
-        let mut fulfillcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
-        let normalized_ty = fulfillcx.normalize_projection_type(
-            &self.infcx,
-            self.param_env,
-            ty::ProjectionTy {
-                item_def_id: tcx.lang_items().deref_target()?,
-                substs: trait_ref.substs,
-            },
+        let normalized_ty = self.infcx.partially_normalize_associated_types_in(
             cause,
+            self.param_env,
+            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);
         if !errors.is_empty() {
             // This shouldn't happen, except for evaluate/fulfill mismatches,
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index a057e45ad6a..78af187cd8f 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -841,6 +841,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                 | ty::PredicateKind::ConstEvaluatable(..)
                 | ty::PredicateKind::Coerce(..)
                 | ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
+                ty::PredicateKind::Ambiguous => return false,
             };
         }
         true
diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
index 8f9d5eaac9d..e8895052353 100644
--- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
@@ -4,11 +4,11 @@ use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::InferCtxt;
 use crate::traits::query::NoSolution;
 use crate::traits::{
-    ChalkEnvironmentAndGoal, FulfillmentError, FulfillmentErrorCode, ObligationCause,
-    PredicateObligation, SelectionError, TraitEngine,
+    ChalkEnvironmentAndGoal, FulfillmentError, FulfillmentErrorCode, PredicateObligation,
+    SelectionError, TraitEngine,
 };
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
-use rustc_middle::ty::{self, Ty, TypeVisitable};
+use rustc_middle::ty::{self, TypeVisitable};
 
 pub struct FulfillmentContext<'tcx> {
     obligations: FxIndexSet<PredicateObligation<'tcx>>,
@@ -33,16 +33,6 @@ impl FulfillmentContext<'_> {
 }
 
 impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
-    fn normalize_projection_type(
-        &mut self,
-        infcx: &InferCtxt<'tcx>,
-        _param_env: ty::ParamEnv<'tcx>,
-        projection_ty: ty::ProjectionTy<'tcx>,
-        _cause: ObligationCause<'tcx>,
-    ) -> Ty<'tcx> {
-        infcx.tcx.mk_ty(ty::Projection(projection_ty))
-    }
-
     fn register_predicate_obligation(
         &mut self,
         infcx: &InferCtxt<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 1ef77e06b48..741bf206d03 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -18,7 +18,7 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::Diagnostic;
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::CRATE_HIR_ID;
-use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::util;
 use rustc_middle::traits::specialization_graph::OverlapMode;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
@@ -94,8 +94,9 @@ pub fn overlapping_impls<'tcx>(
         return None;
     }
 
-    let infcx = tcx.infer_ctxt().build();
-    let selcx = &mut SelectionContext::intercrate(&infcx);
+    let infcx =
+        tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).intercrate().build();
+    let selcx = &mut SelectionContext::new(&infcx);
     let overlaps =
         overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some();
     if !overlaps {
@@ -105,8 +106,9 @@ pub fn overlapping_impls<'tcx>(
     // In the case where we detect an error, run the check again, but
     // this time tracking intercrate ambiguity causes for better
     // diagnostics. (These take time and can lead to false errors.)
-    let infcx = tcx.infer_ctxt().build();
-    let selcx = &mut SelectionContext::intercrate(&infcx);
+    let infcx =
+        tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).intercrate().build();
+    let selcx = &mut SelectionContext::new(&infcx);
     selcx.enable_tracking_intercrate_ambiguity_causes();
     Some(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap())
 }
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 946e6e77a3d..5cb0988919d 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -4,13 +4,12 @@ pub mod suggestions;
 
 use super::{
     FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, ObligationCause,
-    ObligationCauseCode, OutputTypeParameterMismatch, Overflow, PredicateObligation,
-    SelectionContext, SelectionError, TraitNotObjectSafe,
+    ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow,
+    PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe,
 };
 use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::{self, InferCtxt, TyCtxtInferExt};
-use crate::traits::engine::TraitEngineExt as _;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use crate::traits::query::normalize::AtExt as _;
 use crate::traits::specialize::to_pretty_impl_header;
@@ -30,7 +29,6 @@ use rustc_hir::Item;
 use rustc_hir::Node;
 use rustc_infer::infer::error_reporting::TypeErrCtxt;
 use rustc_infer::infer::TypeTrace;
-use rustc_infer::traits::TraitEngine;
 use rustc_middle::traits::select::OverflowError;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::ExpectedFound;
@@ -354,9 +352,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
                     param_env,
                     ty.rebind(ty::TraitPredicate { trait_ref, constness, polarity }),
                 );
-                let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.tcx);
-                fulfill_cx.register_predicate_obligation(self, obligation);
-                if fulfill_cx.select_all_or_error(self).is_empty() {
+                let ocx = ObligationCtxt::new_in_snapshot(self);
+                ocx.register_obligation(obligation);
+                if ocx.select_all_or_error().is_empty() {
                     return Ok((
                         ty::ClosureKind::from_def_id(self.tcx, trait_def_id)
                             .expect("expected to map DefId to ClosureKind"),
@@ -1168,6 +1166,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         )
                     }
 
+                    ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"),
+
                     ty::PredicateKind::TypeWellFormedFromEnv(..) => span_bug!(
                         span,
                         "TypeWellFormedFromEnv predicate should only exist in the environment"
@@ -2112,10 +2112,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 };
 
                 let obligation = obligation.with(self.tcx, trait_ref.to_poly_trait_predicate());
-                let mut selcx = SelectionContext::with_query_mode(
-                    &self,
-                    crate::traits::TraitQueryMode::Standard,
-                );
+                let mut selcx = SelectionContext::new(&self);
                 match selcx.select_from_obligation(&obligation) {
                     Ok(None) => {
                         let impls = ambiguity::recompute_applicable_impls(self.infcx, &obligation);
@@ -2544,7 +2541,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             let obligation =
                 Obligation::new(self.tcx, ObligationCause::dummy(), param_env, cleaned_pred);
 
-            self.predicate_may_hold(&obligation)
+            // We don't use `InferCtxt::predicate_may_hold` because that
+            // will re-run predicates that overflow locally, which ends up
+            // taking a really long time to compute.
+            self.evaluate_obligation(&obligation).map_or(false, |eval| eval.may_apply())
         })
     }
 
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 82f0440b307..9bfe527647d 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
@@ -460,7 +460,7 @@ impl<'tcx> OnUnimplementedDirective {
         info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
 
         let options_map: FxHashMap<Symbol, String> =
-            options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
+            options.iter().filter_map(|(k, v)| v.clone().map(|v| (*k, v))).collect();
 
         for command in self.subcommands.iter().chain(Some(self)).rev() {
             if let Some(ref condition) = command.condition && !attr::eval_condition(
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 8086cac0d55..30207033236 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1340,9 +1340,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     obligation.param_env,
                     trait_pred_and_suggested_ty,
                 );
-                let suggested_ty_would_satisfy_obligation = self
-                    .evaluate_obligation_no_overflow(&new_obligation)
-                    .must_apply_modulo_regions();
+                let suggested_ty_would_satisfy_obligation =
+                    self.predicate_must_hold_modulo_regions(&new_obligation);
                 if suggested_ty_would_satisfy_obligation {
                     let sp = self
                         .tcx
@@ -1886,13 +1885,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         //
         // - `BuiltinDerivedObligation` with a generator witness (B)
         // - `BuiltinDerivedObligation` with a generator (B)
-        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
         // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
         // - `BuiltinDerivedObligation` with a generator witness (A)
         // - `BuiltinDerivedObligation` with a generator (A)
-        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
         // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
         // - `BindingObligation` with `impl_send (Send requirement)
         //
@@ -2625,30 +2620,24 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     }
                 };
 
-                let from_generator = tcx.lang_items().from_generator_fn().unwrap();
+                let identity_future = tcx.require_lang_item(LangItem::IdentityFuture, None);
 
                 // Don't print the tuple of capture types
                 'print: {
                     if !is_upvar_tys_infer_tuple {
                         let msg = format!("required because it appears within the type `{}`", ty);
                         match ty.kind() {
-                            ty::Adt(def, _) => {
-                                // `gen_future` is used in all async functions; it doesn't add any additional info.
-                                if self.tcx.is_diagnostic_item(sym::gen_future, def.did()) {
-                                    break 'print;
-                                }
-                                match self.tcx.opt_item_ident(def.did()) {
-                                    Some(ident) => err.span_note(ident.span, &msg),
-                                    None => err.note(&msg),
-                                }
-                            }
+                            ty::Adt(def, _) => match self.tcx.opt_item_ident(def.did()) {
+                                Some(ident) => err.span_note(ident.span, &msg),
+                                None => err.note(&msg),
+                            },
                             ty::Opaque(def_id, _) => {
-                                // Avoid printing the future from `core::future::from_generator`, it's not helpful
-                                if tcx.parent(*def_id) == from_generator {
+                                // Avoid printing the future from `core::future::identity_future`, it's not helpful
+                                if tcx.parent(*def_id) == identity_future {
                                     break 'print;
                                 }
 
-                                // If the previous type is `from_generator`, this is the future generated by the body of an async function.
+                                // If the previous type is `identity_future`, this is the future generated by the body of an async function.
                                 // Avoid printing it twice (it was already printed in the `ty::Generator` arm below).
                                 let is_future = tcx.ty_is_opaque_future(ty);
                                 debug!(
@@ -2658,8 +2647,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 );
                                 if is_future
                                     && obligated_types.last().map_or(false, |ty| match ty.kind() {
-                                        ty::Opaque(last_def_id, _) => {
-                                            tcx.parent(*last_def_id) == from_generator
+                                        ty::Generator(last_def_id, ..) => {
+                                            matches!(
+                                                tcx.generator_kind(last_def_id),
+                                                Some(GeneratorKind::Async(..))
+                                            )
                                         }
                                         _ => false,
                                     })
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index d84f768cce4..e7513255dc4 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -4,12 +4,12 @@ use rustc_data_structures::obligation_forest::ProcessResult;
 use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
 use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
 use rustc_infer::traits::ProjectionCacheKey;
-use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
+use rustc_infer::traits::{SelectionError, TraitEngine, TraitObligation};
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, Binder, Const, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Binder, Const, TypeVisitable};
 use std::marker::PhantomData;
 
 use super::const_evaluatable;
@@ -20,9 +20,9 @@ use super::CodeAmbiguity;
 use super::CodeProjectionError;
 use super::CodeSelectionError;
 use super::EvaluationResult;
+use super::PredicateObligation;
 use super::Unimplemented;
 use super::{FulfillmentError, FulfillmentErrorCode};
-use super::{ObligationCause, PredicateObligation};
 
 use crate::traits::project::PolyProjectionObligation;
 use crate::traits::project::ProjectionCacheKeyExt as _;
@@ -126,42 +126,6 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
 }
 
 impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
-    /// "Normalize" a projection type `<SomeType as SomeTrait>::X` by
-    /// creating a fresh type variable `$0` as well as a projection
-    /// predicate `<SomeType as SomeTrait>::X == $0`. When the
-    /// inference engine runs, it will attempt to find an impl of
-    /// `SomeTrait` or a where-clause that lets us unify `$0` with
-    /// something concrete. If this fails, we'll unify `$0` with
-    /// `projection_ty` again.
-    #[instrument(level = "debug", skip(self, infcx, param_env, cause))]
-    fn normalize_projection_type(
-        &mut self,
-        infcx: &InferCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        projection_ty: ty::ProjectionTy<'tcx>,
-        cause: ObligationCause<'tcx>,
-    ) -> Ty<'tcx> {
-        debug_assert!(!projection_ty.has_escaping_bound_vars());
-
-        // FIXME(#20304) -- cache
-
-        let mut selcx = SelectionContext::new(infcx);
-        let mut obligations = vec![];
-        let normalized_ty = project::normalize_projection_type(
-            &mut selcx,
-            param_env,
-            projection_ty,
-            cause,
-            0,
-            &mut obligations,
-        );
-        self.register_predicate_obligations(infcx, obligations);
-
-        debug!(?normalized_ty);
-
-        normalized_ty.ty().unwrap()
-    }
-
     fn register_predicate_obligation(
         &mut self,
         infcx: &InferCtxt<'tcx>,
@@ -336,6 +300,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder));
                     ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)]))
                 }
+                ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
                 ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                     bug!("TypeWellFormedFromEnv is only used for Chalk")
                 }
@@ -569,6 +534,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         }
                     }
                 }
+                ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
                 ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                     bug!("TypeWellFormedFromEnv is only used for Chalk")
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index ff18aa1f9e9..548ca1c1d7f 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -31,7 +31,6 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
-use rustc_infer::traits::TraitEngineExt as _;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{
@@ -403,9 +402,7 @@ pub fn fully_solve_obligation<'tcx>(
     infcx: &InferCtxt<'tcx>,
     obligation: PredicateObligation<'tcx>,
 ) -> Vec<FulfillmentError<'tcx>> {
-    let mut engine = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
-    engine.register_predicate_obligation(infcx, obligation);
-    engine.select_all_or_error(infcx)
+    fully_solve_obligations(infcx, [obligation])
 }
 
 /// Process a set of obligations (and any nested obligations that come from them)
@@ -414,9 +411,9 @@ pub fn fully_solve_obligations<'tcx>(
     infcx: &InferCtxt<'tcx>,
     obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
 ) -> Vec<FulfillmentError<'tcx>> {
-    let mut engine = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
-    engine.register_predicate_obligations(infcx, obligations);
-    engine.select_all_or_error(infcx)
+    let ocx = ObligationCtxt::new(infcx);
+    ocx.register_obligations(obligations);
+    ocx.select_all_or_error()
 }
 
 /// Process a bound (and any nested obligations that come from it) to completion.
@@ -429,9 +426,16 @@ pub fn fully_solve_bound<'tcx>(
     ty: Ty<'tcx>,
     bound: DefId,
 ) -> Vec<FulfillmentError<'tcx>> {
-    let mut engine = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
-    engine.register_bound(infcx, param_env, ty, bound, cause);
-    engine.select_all_or_error(infcx)
+    let tcx = infcx.tcx;
+    let trait_ref = ty::TraitRef { def_id: bound, substs: tcx.mk_substs_trait(ty, []) };
+    let obligation = Obligation {
+        cause,
+        recursion_depth: 0,
+        param_env,
+        predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
+    };
+
+    fully_solve_obligation(infcx, obligation)
 }
 
 /// Normalizes the predicates and checks whether they hold in an empty environment. If this
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 90f48658113..7c4c58ba361 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -319,6 +319,7 @@ fn predicate_references_self<'tcx>(
         | ty::PredicateKind::Coerce(..)
         | ty::PredicateKind::ConstEvaluatable(..)
         | ty::PredicateKind::ConstEquate(..)
+        | ty::PredicateKind::Ambiguous
         | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
     }
 }
@@ -350,6 +351,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
             | ty::PredicateKind::TypeOutlives(..)
             | ty::PredicateKind::ConstEvaluatable(..)
             | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::Ambiguous
             | ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
         }
     })
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 9f19b0092c0..f17d702d421 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -12,7 +12,8 @@ use super::SelectionContext;
 use super::SelectionError;
 use super::{
     ImplSourceClosureData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData,
-    ImplSourceGeneratorData, ImplSourcePointeeData, ImplSourceUserDefinedData,
+    ImplSourceFutureData, ImplSourceGeneratorData, ImplSourcePointeeData,
+    ImplSourceUserDefinedData,
 };
 use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
 
@@ -566,22 +567,6 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
                     .flatten()
                     .unwrap_or_else(|| ty.super_fold_with(self).into())
                 };
-                // For cases like #95134 we would like to catch overflows early
-                // otherwise they slip away and cause ICE.
-                let recursion_limit = self.tcx().recursion_limit();
-                if !recursion_limit.value_within_limit(self.depth)
-                    // HACK: Don't overflow when running cargo doc see #100991
-                    && !self.tcx().sess.opts.actually_rustdoc
-                {
-                    let obligation = Obligation::with_depth(
-                        self.selcx.tcx(),
-                        self.cause.clone(),
-                        recursion_limit.0,
-                        self.param_env,
-                        ty,
-                    );
-                    self.selcx.infcx().err_ctxt().report_overflow_error(&obligation, true);
-                }
                 debug!(
                     ?self.depth,
                     ?ty,
@@ -1560,6 +1545,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
         let eligible = match &impl_source {
             super::ImplSource::Closure(_)
             | super::ImplSource::Generator(_)
+            | super::ImplSource::Future(_)
             | super::ImplSource::FnPointer(_)
             | super::ImplSource::TraitAlias(_) => true,
             super::ImplSource::UserDefined(impl_data) => {
@@ -1848,6 +1834,7 @@ fn confirm_select_candidate<'cx, 'tcx>(
     match impl_source {
         super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
         super::ImplSource::Generator(data) => confirm_generator_candidate(selcx, obligation, data),
+        super::ImplSource::Future(data) => confirm_future_candidate(selcx, obligation, data),
         super::ImplSource::Closure(data) => confirm_closure_candidate(selcx, obligation, data),
         super::ImplSource::FnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data),
         super::ImplSource::DiscriminantKind(data) => {
@@ -1921,6 +1908,48 @@ fn confirm_generator_candidate<'cx, 'tcx>(
         .with_addl_obligations(obligations)
 }
 
+fn confirm_future_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    impl_source: ImplSourceFutureData<'tcx, PredicateObligation<'tcx>>,
+) -> Progress<'tcx> {
+    let gen_sig = impl_source.substs.as_generator().poly_sig();
+    let Normalized { value: gen_sig, obligations } = normalize_with_depth(
+        selcx,
+        obligation.param_env,
+        obligation.cause.clone(),
+        obligation.recursion_depth + 1,
+        gen_sig,
+    );
+
+    debug!(?obligation, ?gen_sig, ?obligations, "confirm_future_candidate");
+
+    let tcx = selcx.tcx();
+    let fut_def_id = tcx.require_lang_item(LangItem::Future, None);
+
+    let predicate = super::util::future_trait_ref_and_outputs(
+        tcx,
+        fut_def_id,
+        obligation.predicate.self_ty(),
+        gen_sig,
+    )
+    .map_bound(|(trait_ref, return_ty)| {
+        debug_assert_eq!(tcx.associated_item(obligation.predicate.item_def_id).name, sym::Output);
+
+        ty::ProjectionPredicate {
+            projection_ty: ty::ProjectionTy {
+                substs: trait_ref.substs,
+                item_def_id: obligation.predicate.item_def_id,
+            },
+            term: return_ty.into(),
+        }
+    });
+
+    confirm_param_env_candidate(selcx, obligation, predicate, false)
+        .with_addl_obligations(impl_source.nested)
+        .with_addl_obligations(obligations)
+}
+
 fn confirm_discriminant_kind_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
index c84f128ddf7..4a419fbe952 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -2,9 +2,7 @@ use rustc_middle::ty;
 
 use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::InferCtxt;
-use crate::traits::{
-    EvaluationResult, OverflowError, PredicateObligation, SelectionContext, TraitQueryMode,
-};
+use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext};
 
 pub trait InferCtxtExt<'tcx> {
     fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool;
@@ -97,7 +95,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         match self.evaluate_obligation(obligation) {
             Ok(result) => result,
             Err(OverflowError::Canonical) => {
-                let mut selcx = SelectionContext::with_query_mode(&self, TraitQueryMode::Standard);
+                let mut selcx = SelectionContext::new(&self);
                 selcx.evaluate_root_obligation(obligation).unwrap_or_else(|r| match r {
                     OverflowError::Canonical => {
                         span_bug!(
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 3b107d9570f..c7983ecbd43 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -6,11 +6,9 @@
 //!
 //! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly
 use hir::LangItem;
-use rustc_errors::DelayDm;
 use rustc_hir as hir;
 use rustc_infer::traits::ObligationCause;
 use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
-use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, Ty, TypeVisitable};
 use rustc_target::spec::abi::Abi;
@@ -314,7 +312,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates);
                 }
 
-                self.assemble_generator_candidates(obligation, &mut candidates);
+                if lang_items.gen_trait() == Some(def_id) {
+                    self.assemble_generator_candidates(obligation, &mut candidates);
+                } else if lang_items.future_trait() == Some(def_id) {
+                    self.assemble_future_candidates(obligation, &mut candidates);
+                }
+
                 self.assemble_closure_candidates(obligation, &mut candidates);
                 self.assemble_fn_pointer_candidates(obligation, &mut candidates);
                 self.assemble_candidates_from_impls(obligation, &mut candidates);
@@ -402,10 +405,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligation: &TraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
-        if self.tcx().lang_items().gen_trait() != Some(obligation.predicate.def_id()) {
-            return;
-        }
-
         // Okay to skip binder because the substs on generator types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters.
@@ -424,6 +423,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
     }
 
+    fn assemble_future_candidates(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) {
+        let self_ty = obligation.self_ty().skip_binder();
+        if let ty::Generator(did, ..) = self_ty.kind() {
+            if let Some(rustc_hir::GeneratorKind::Async(_generator_kind)) =
+                self.tcx().generator_kind(did)
+            {
+                debug!(?self_ty, ?obligation, "assemble_future_candidates",);
+
+                candidates.vec.push(FutureCandidate);
+            }
+        }
+    }
+
     /// Checks for the artificial impl that the compiler will create for an obligation like `X :
     /// FnMut<..>` where `X` is a closure type.
     ///
@@ -776,9 +792,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         match (source.kind(), target.kind()) {
             // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
-            (&ty::Dynamic(ref data_a, _, dyn_a), &ty::Dynamic(ref data_b, _, dyn_b))
-                if dyn_a == dyn_b =>
-            {
+            (&ty::Dynamic(ref data_a, _, ty::Dyn), &ty::Dynamic(ref data_b, _, ty::Dyn)) => {
                 // Upcast coercions permit several things:
                 //
                 // 1. Dropping auto traits, e.g., `Foo + Send` to `Foo`
@@ -811,16 +825,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             &obligation.cause,
                         ) {
                             if deref_trait_ref.def_id() == target_trait_did {
-                                self.tcx().struct_span_lint_hir(
-                                    DEREF_INTO_DYN_SUPERTRAIT,
-                                    obligation.cause.body_id,
-                                    obligation.cause.span,
-                                    DelayDm(|| format!(
-                                        "`{}` implements `Deref` with supertrait `{}` as output",
-                                        source, deref_trait_ref
-                                    )),
-                                    |lint| lint,
-                                );
                                 return;
                             }
                         }
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 2ec5d925b69..e46441001b5 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -23,10 +23,11 @@ use crate::traits::{
     BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
     ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
     ImplSourceConstDestructData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData,
-    ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData,
-    ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, ObjectCastObligation,
-    Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection,
-    SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented, VtblSegment,
+    ImplSourceFutureData, ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData,
+    ImplSourceTraitAliasData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized,
+    ObjectCastObligation, Obligation, ObligationCause, OutputTypeParameterMismatch,
+    PredicateObligation, Selection, SelectionError, TraitNotObjectSafe, TraitObligation,
+    Unimplemented, VtblSegment,
 };
 
 use super::BuiltinImplConditions;
@@ -89,6 +90,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ImplSource::Generator(vtable_generator)
             }
 
+            FutureCandidate => {
+                let vtable_future = self.confirm_future_candidate(obligation)?;
+                ImplSource::Future(vtable_future)
+            }
+
             FnPointerCandidate { .. } => {
                 let data = self.confirm_fn_pointer_candidate(obligation)?;
                 ImplSource::FnPointer(data)
@@ -599,8 +605,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     {
         debug!(?obligation, "confirm_fn_pointer_candidate");
 
-        // Okay to skip binder; it is reintroduced below.
-        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
+        let self_ty = self
+            .infcx
+            .shallow_resolve(obligation.self_ty().no_bound_vars())
+            .expect("fn pointer should not capture bound vars from predicate");
         let sig = self_ty.fn_sig(self.tcx());
         let trait_ref = closure_trait_ref_and_return_type(
             self.tcx(),
@@ -615,15 +623,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         // Confirm the `type Output: Sized;` bound that is present on `FnOnce`
         let cause = obligation.derived_cause(BuiltinDerivedObligation);
-        // The binder on the Fn obligation is "less" important than the one on
-        // the signature, as evidenced by how we treat it during projection.
-        // The safe thing to do here is to liberate it, though, which should
-        // have no worse effect than skipping the binder here.
-        let liberated_fn_ty =
-            self.infcx.replace_bound_vars_with_placeholders(obligation.predicate.rebind(self_ty));
-        let output_ty = self
-            .infcx
-            .replace_bound_vars_with_placeholders(liberated_fn_ty.fn_sig(self.tcx()).output());
+        let output_ty = self.infcx.replace_bound_vars_with_placeholders(sig.output());
         let output_ty = normalize_with_depth_to(
             self,
             obligation.param_env,
@@ -685,7 +685,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         debug!(?obligation, ?generator_def_id, ?substs, "confirm_generator_candidate");
 
-        let trait_ref = self.generator_trait_ref_unnormalized(obligation, substs);
+        let gen_sig = substs.as_generator().poly_sig();
+
+        // NOTE: The self-type is a generator type and hence is
+        // in fact unparameterized (or at least does not reference any
+        // regions bound in the obligation).
+        let self_ty = obligation
+            .predicate
+            .self_ty()
+            .no_bound_vars()
+            .expect("unboxed closure type should not capture bound vars from the predicate");
+
+        let trait_ref = super::util::generator_trait_ref_and_outputs(
+            self.tcx(),
+            obligation.predicate.def_id(),
+            self_ty,
+            gen_sig,
+        )
+        .map_bound(|(trait_ref, ..)| trait_ref);
 
         let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
         debug!(?trait_ref, ?nested, "generator candidate obligations");
@@ -693,6 +710,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         Ok(ImplSourceGeneratorData { generator_def_id, substs, nested })
     }
 
+    fn confirm_future_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> Result<ImplSourceFutureData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+        // Okay to skip binder because the substs on generator types never
+        // touch bound regions, they just capture the in-scope
+        // type/region parameters.
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
+        let ty::Generator(generator_def_id, substs, _) = *self_ty.kind() else {
+            bug!("closure candidate for non-closure {:?}", obligation);
+        };
+
+        debug!(?obligation, ?generator_def_id, ?substs, "confirm_future_candidate");
+
+        let gen_sig = substs.as_generator().poly_sig();
+
+        let trait_ref = super::util::future_trait_ref_and_outputs(
+            self.tcx(),
+            obligation.predicate.def_id(),
+            obligation.predicate.no_bound_vars().expect("future has no bound vars").self_ty(),
+            gen_sig,
+        )
+        .map_bound(|(trait_ref, ..)| trait_ref);
+
+        let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
+        debug!(?trait_ref, ?nested, "future candidate obligations");
+
+        Ok(ImplSourceFutureData { generator_def_id, substs, nested })
+    }
+
     #[instrument(skip(self), level = "debug")]
     fn confirm_closure_candidate(
         &mut self,
@@ -803,9 +850,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let upcast_trait_ref;
         match (source.kind(), target.kind()) {
             // TraitA+Kx+'a -> TraitB+Ky+'b (trait upcasting coercion).
-            (&ty::Dynamic(ref data_a, r_a, repr_a), &ty::Dynamic(ref data_b, r_b, repr_b))
-                if repr_a == repr_b =>
-            {
+            (
+                &ty::Dynamic(ref data_a, r_a, repr_a @ ty::Dyn),
+                &ty::Dynamic(ref data_b, r_b, ty::Dyn),
+            ) => {
                 // See `assemble_candidates_for_unsizing` for more info.
                 // We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
                 let principal_a = data_a.principal().unwrap();
@@ -831,7 +879,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             .map(ty::Binder::dummy),
                     );
                 let existential_predicates = tcx.mk_poly_existential_predicates(iter);
-                let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_b);
+                let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_a);
 
                 // Require that the traits involved in this upcast are **equal**;
                 // only the **lifetime bound** is changed.
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index e54e290fb4b..2a1494e8952 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -110,25 +110,6 @@ pub struct SelectionContext<'cx, 'tcx> {
     /// require themselves.
     freshener: TypeFreshener<'cx, 'tcx>,
 
-    /// During coherence we have to assume that other crates may add
-    /// additional impls which we currently don't know about.
-    ///
-    /// To deal with this evaluation should be conservative
-    /// and consider the possibility of impls from outside this crate.
-    /// This comes up primarily when resolving ambiguity. Imagine
-    /// there is some trait reference `$0: Bar` where `$0` is an
-    /// inference variable. If `intercrate` is true, then we can never
-    /// say for sure that this reference is not implemented, even if
-    /// there are *no impls at all for `Bar`*, because `$0` could be
-    /// bound to some type that in a downstream crate that implements
-    /// `Bar`.
-    ///
-    /// Outside of coherence we set this to false because we are only
-    /// interested in types that the user could actually have written.
-    /// In other words, we consider `$0: Bar` to be unimplemented if
-    /// there is no type that the user could *actually name* that
-    /// would satisfy it. This avoids crippling inference, basically.
-    intercrate: bool,
     /// If `intercrate` is set, we remember predicates which were
     /// considered ambiguous because of impls potentially added in other crates.
     /// This is used in coherence to give improved diagnostics.
@@ -226,16 +207,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         SelectionContext {
             infcx,
             freshener: infcx.freshener_keep_static(),
-            intercrate: false,
             intercrate_ambiguity_causes: None,
             query_mode: TraitQueryMode::Standard,
         }
     }
 
-    pub fn intercrate(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> {
-        SelectionContext { intercrate: true, ..SelectionContext::new(infcx) }
-    }
-
     pub fn with_query_mode(
         infcx: &'cx InferCtxt<'tcx>,
         query_mode: TraitQueryMode,
@@ -247,7 +223,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// Enables tracking of intercrate ambiguity causes. See
     /// the documentation of [`Self::intercrate_ambiguity_causes`] for more.
     pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
-        assert!(self.intercrate);
+        assert!(self.is_intercrate());
         assert!(self.intercrate_ambiguity_causes.is_none());
         self.intercrate_ambiguity_causes = Some(FxIndexSet::default());
         debug!("selcx: enable_tracking_intercrate_ambiguity_causes");
@@ -257,7 +233,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// was enabled and disables tracking at the same time. If
     /// tracking is not enabled, just returns an empty vector.
     pub fn take_intercrate_ambiguity_causes(&mut self) -> FxIndexSet<IntercrateAmbiguityCause> {
-        assert!(self.intercrate);
+        assert!(self.is_intercrate());
         self.intercrate_ambiguity_causes.take().unwrap_or_default()
     }
 
@@ -270,7 +246,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     }
 
     pub fn is_intercrate(&self) -> bool {
-        self.intercrate
+        self.infcx.intercrate
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -741,6 +717,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                     bug!("TypeWellFormedFromEnv is only used for chalk")
                 }
+                ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
             }
         })
     }
@@ -751,7 +728,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         previous_stack: TraitObligationStackList<'o, 'tcx>,
         mut obligation: TraitObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
-        if !self.intercrate
+        if !self.is_intercrate()
             && obligation.is_global()
             && obligation.param_env.caller_bounds().iter().all(|bound| bound.needs_subst())
         {
@@ -1014,7 +991,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // mode, so don't do any caching. In particular, we might
         // re-use the same `InferCtxt` with both an intercrate
         // and non-intercrate `SelectionContext`
-        if self.intercrate {
+        if self.is_intercrate() {
             return None;
         }
 
@@ -1044,7 +1021,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // mode, so don't do any caching. In particular, we might
         // re-use the same `InferCtxt` with both an intercrate
         // and non-intercrate `SelectionContext`
-        if self.intercrate {
+        if self.is_intercrate() {
             return;
         }
 
@@ -1162,9 +1139,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     ProjectionCandidate(_, ty::BoundConstness::ConstIfConst) => {}
                     // auto trait impl
                     AutoImplCandidate => {}
-                    // generator, this will raise error in other places
+                    // generator / future, this will raise error in other places
                     // or ignore error with const_async_blocks feature
                     GeneratorCandidate => {}
+                    FutureCandidate => {}
                     // FnDef where the function is const
                     FnPointerCandidate { is_const: true } => {}
                     ConstDestructCandidate(_) => {}
@@ -1225,9 +1203,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     }
 
     fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> {
-        debug!("is_knowable(intercrate={:?})", self.intercrate);
+        debug!("is_knowable(intercrate={:?})", self.is_intercrate());
 
-        if !self.intercrate || stack.obligation.polarity() == ty::ImplPolarity::Negative {
+        if !self.is_intercrate() || stack.obligation.polarity() == ty::ImplPolarity::Negative {
             return Ok(());
         }
 
@@ -1258,7 +1236,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // the master cache. Since coherence executes pretty quickly,
         // it's not worth going to more trouble to increase the
         // hit-rate, I don't think.
-        if self.intercrate {
+        if self.is_intercrate() {
             return false;
         }
 
@@ -1275,7 +1253,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // mode, so don't do any caching. In particular, we might
         // re-use the same `InferCtxt` with both an intercrate
         // and non-intercrate `SelectionContext`
-        if self.intercrate {
+        if self.is_intercrate() {
             return None;
         }
         let tcx = self.tcx();
@@ -1314,7 +1292,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // mode, so don't do any caching. In particular, we might
         // re-use the same `InferCtxt` with both an intercrate
         // and non-intercrate `SelectionContext`
-        if self.intercrate {
+        if self.is_intercrate() {
             return false;
         }
         match result {
@@ -1643,6 +1621,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ImplCandidate(..)
                 | ClosureCandidate
                 | GeneratorCandidate
+                | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
@@ -1661,6 +1640,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ImplCandidate(_)
                 | ClosureCandidate
                 | GeneratorCandidate
+                | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
@@ -1691,6 +1671,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ImplCandidate(..)
                 | ClosureCandidate
                 | GeneratorCandidate
+                | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
@@ -1703,6 +1684,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ImplCandidate(..)
                 | ClosureCandidate
                 | GeneratorCandidate
+                | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
@@ -1784,6 +1766,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ImplCandidate(_)
                 | ClosureCandidate
                 | GeneratorCandidate
+                | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
@@ -1793,6 +1776,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ImplCandidate(_)
                 | ClosureCandidate
                 | GeneratorCandidate
+                | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
@@ -2191,7 +2175,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{e}`"))?;
         nested_obligations.extend(obligations);
 
-        if !self.intercrate
+        if !self.is_intercrate()
             && self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
         {
             debug!("reservation impls only apply in intercrate mode");
@@ -2287,43 +2271,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         debug!(?closure_sig);
 
-        // (1) Feels icky to skip the binder here, but OTOH we know
-        // that the self-type is an unboxed closure type and hence is
+        // NOTE: The self-type is an unboxed closure type and hence is
         // in fact unparameterized (or at least does not reference any
-        // regions bound in the obligation). Still probably some
-        // refactoring could make this nicer.
+        // regions bound in the obligation).
+        let self_ty = obligation
+            .predicate
+            .self_ty()
+            .no_bound_vars()
+            .expect("unboxed closure type should not capture bound vars from the predicate");
+
         closure_trait_ref_and_return_type(
             self.tcx(),
             obligation.predicate.def_id(),
-            obligation.predicate.skip_binder().self_ty(), // (1)
+            self_ty,
             closure_sig,
             util::TupleArgumentsFlag::No,
         )
         .map_bound(|(trait_ref, _)| trait_ref)
     }
 
-    fn generator_trait_ref_unnormalized(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        substs: SubstsRef<'tcx>,
-    ) -> ty::PolyTraitRef<'tcx> {
-        let gen_sig = substs.as_generator().poly_sig();
-
-        // (1) Feels icky to skip the binder here, but OTOH we know
-        // that the self-type is an generator type and hence is
-        // in fact unparameterized (or at least does not reference any
-        // regions bound in the obligation). Still probably some
-        // refactoring could make this nicer.
-
-        super::util::generator_trait_ref_and_outputs(
-            self.tcx(),
-            obligation.predicate.def_id(),
-            obligation.predicate.skip_binder().self_ty(), // (1)
-            gen_sig,
-        )
-        .map_bound(|(trait_ref, ..)| trait_ref)
-    }
-
     /// Returns the obligations that are implied by instantiating an
     /// impl or trait. The obligations are substituted and fully
     /// normalized. This is used when confirming an impl or default
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 7cc12eff20e..9a3c0707c7c 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -10,14 +10,14 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
 
 pub mod specialization_graph;
-use rustc_infer::traits::{TraitEngine, TraitEngineExt as _};
 use specialization_graph::GraphExt;
 
 use crate::errors::NegativePositiveConflict;
 use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
-use crate::traits::engine::TraitEngineExt as _;
 use crate::traits::select::IntercrateAmbiguityCause;
-use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause};
+use crate::traits::{
+    self, coherence, FutureCompatOverlapErrorKind, ObligationCause, ObligationCtxt,
+};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{error_code, DelayDm, Diagnostic};
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -204,12 +204,12 @@ fn fulfill_implication<'tcx>(
 
     // Needs to be `in_snapshot` because this function is used to rebase
     // substitutions, which may happen inside of a select within a probe.
-    let mut engine = <dyn TraitEngine<'tcx>>::new_in_snapshot(infcx.tcx);
+    let ocx = ObligationCtxt::new_in_snapshot(infcx);
     // attempt to prove all of the predicates for impl2 given those for impl1
     // (which are packed up in penv)
-    engine.register_predicate_obligations(infcx, obligations.chain(more_obligations));
+    ocx.register_obligations(obligations.chain(more_obligations));
 
-    let errors = engine.select_all_or_error(infcx);
+    let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
         // no dice!
         debug!(
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index 932dbbb81e5..40dbe0b3ff0 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -1,6 +1,5 @@
 use crate::infer::{InferCtxt, TyCtxtInferExt};
-use crate::traits::ObligationCause;
-use crate::traits::{TraitEngine, TraitEngineExt};
+use crate::traits::{ObligationCause, ObligationCtxt};
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
@@ -72,28 +71,16 @@ fn type_marked_structural<'tcx>(
     adt_ty: Ty<'tcx>,
     cause: ObligationCause<'tcx>,
 ) -> bool {
-    let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
+    let ocx = ObligationCtxt::new(infcx);
     // require `#[derive(PartialEq)]`
     let structural_peq_def_id =
         infcx.tcx.require_lang_item(LangItem::StructuralPeq, Some(cause.span));
-    fulfillment_cx.register_bound(
-        infcx,
-        ty::ParamEnv::empty(),
-        adt_ty,
-        structural_peq_def_id,
-        cause.clone(),
-    );
+    ocx.register_bound(cause.clone(), ty::ParamEnv::empty(), adt_ty, structural_peq_def_id);
     // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around
     // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.)
     let structural_teq_def_id =
         infcx.tcx.require_lang_item(LangItem::StructuralTeq, Some(cause.span));
-    fulfillment_cx.register_bound(
-        infcx,
-        ty::ParamEnv::empty(),
-        adt_ty,
-        structural_teq_def_id,
-        cause,
-    );
+    ocx.register_bound(cause, ty::ParamEnv::empty(), adt_ty, structural_teq_def_id);
 
     // We deliberately skip *reporting* fulfillment errors (via
     // `report_fulfillment_errors`), for two reasons:
@@ -104,7 +91,7 @@ fn type_marked_structural<'tcx>(
     //
     // 2. We are sometimes doing future-incompatibility lints for
     //    now, so we do not want unconditional errors here.
-    fulfillment_cx.select_all_or_error(infcx).is_empty()
+    ocx.select_all_or_error().is_empty()
 }
 
 /// This implements the traversal over the structure of a given type to try to
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 895b84fd7e9..a496cea0b00 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -298,11 +298,11 @@ pub fn closure_trait_ref_and_return_type<'tcx>(
     sig: ty::PolyFnSig<'tcx>,
     tuple_arguments: TupleArgumentsFlag,
 ) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>)> {
+    assert!(!self_ty.has_escaping_bound_vars());
     let arguments_tuple = match tuple_arguments {
         TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
         TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()),
     };
-    debug_assert!(!self_ty.has_escaping_bound_vars());
     let trait_ref = tcx.mk_trait_ref(fn_trait_def_id, [self_ty, arguments_tuple]);
     sig.map_bound(|sig| (trait_ref, sig.output()))
 }
@@ -313,11 +313,22 @@ pub fn generator_trait_ref_and_outputs<'tcx>(
     self_ty: Ty<'tcx>,
     sig: ty::PolyGenSig<'tcx>,
 ) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
-    debug_assert!(!self_ty.has_escaping_bound_vars());
+    assert!(!self_ty.has_escaping_bound_vars());
     let trait_ref = tcx.mk_trait_ref(fn_trait_def_id, [self_ty, sig.skip_binder().resume_ty]);
     sig.map_bound(|sig| (trait_ref, sig.yield_ty, sig.return_ty))
 }
 
+pub fn future_trait_ref_and_outputs<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    fn_trait_def_id: DefId,
+    self_ty: Ty<'tcx>,
+    sig: ty::PolyGenSig<'tcx>,
+) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>)> {
+    assert!(!self_ty.has_escaping_bound_vars());
+    let trait_ref = tcx.mk_trait_ref(fn_trait_def_id, [self_ty]);
+    sig.map_bound(|sig| (trait_ref, sig.return_ty))
+}
+
 pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
     assoc_item.defaultness(tcx).is_final()
         && tcx.impl_defaultness(assoc_item.container_id(tcx)).is_final()
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 53783e1bc4b..5e506a23f38 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -155,6 +155,7 @@ pub fn predicate_obligations<'tcx>(
             wf.compute(c1.into());
             wf.compute(c2.into());
         }
+        ty::PredicateKind::Ambiguous => {}
         ty::PredicateKind::TypeWellFormedFromEnv(..) => {
             bug!("TypeWellFormedFromEnv is only used for Chalk")
         }
@@ -875,6 +876,7 @@ pub(crate) fn required_region_bounds<'tcx>(
                 | ty::PredicateKind::RegionOutlives(..)
                 | ty::PredicateKind::ConstEvaluatable(..)
                 | ty::PredicateKind::ConstEquate(..)
+                | ty::PredicateKind::Ambiguous
                 | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
                 ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
                     // Search for a bound of the form `erased_self_ty
diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml
index 9474e6df567..a432498abcc 100644
--- a/compiler/rustc_traits/Cargo.toml
+++ b/compiler/rustc_traits/Cargo.toml
@@ -12,6 +12,7 @@ rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_span = { path = "../rustc_span" }
+rustc_target = { path = "../rustc_target" }
 chalk-ir = "0.87.0"
 chalk-engine = "0.87.0"
 chalk-solve = "0.87.0"
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index d15707e5ced..344c8b93c17 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -9,9 +9,9 @@
 use rustc_middle::traits::ChalkRustInterner as RustInterner;
 use rustc_middle::ty::{self, AssocKind, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
 use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_target::abi::{Integer, IntegerType};
 
 use rustc_ast::ast;
-use rustc_attr as attr;
 
 use rustc_hir::def_id::DefId;
 
@@ -218,21 +218,21 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
             c: adt_def.repr().c(),
             packed: adt_def.repr().packed(),
             int: adt_def.repr().int.map(|i| match i {
-                attr::IntType::SignedInt(ty) => match ty {
-                    ast::IntTy::Isize => int(chalk_ir::IntTy::Isize),
-                    ast::IntTy::I8 => int(chalk_ir::IntTy::I8),
-                    ast::IntTy::I16 => int(chalk_ir::IntTy::I16),
-                    ast::IntTy::I32 => int(chalk_ir::IntTy::I32),
-                    ast::IntTy::I64 => int(chalk_ir::IntTy::I64),
-                    ast::IntTy::I128 => int(chalk_ir::IntTy::I128),
+                IntegerType::Pointer(true) => int(chalk_ir::IntTy::Isize),
+                IntegerType::Pointer(false) => uint(chalk_ir::UintTy::Usize),
+                IntegerType::Fixed(i, true) => match i {
+                    Integer::I8 => int(chalk_ir::IntTy::I8),
+                    Integer::I16 => int(chalk_ir::IntTy::I16),
+                    Integer::I32 => int(chalk_ir::IntTy::I32),
+                    Integer::I64 => int(chalk_ir::IntTy::I64),
+                    Integer::I128 => int(chalk_ir::IntTy::I128),
                 },
-                attr::IntType::UnsignedInt(ty) => match ty {
-                    ast::UintTy::Usize => uint(chalk_ir::UintTy::Usize),
-                    ast::UintTy::U8 => uint(chalk_ir::UintTy::U8),
-                    ast::UintTy::U16 => uint(chalk_ir::UintTy::U16),
-                    ast::UintTy::U32 => uint(chalk_ir::UintTy::U32),
-                    ast::UintTy::U64 => uint(chalk_ir::UintTy::U64),
-                    ast::UintTy::U128 => uint(chalk_ir::UintTy::U128),
+                IntegerType::Fixed(i, false) => match i {
+                    Integer::I8 => uint(chalk_ir::UintTy::U8),
+                    Integer::I16 => uint(chalk_ir::UintTy::U16),
+                    Integer::I32 => uint(chalk_ir::UintTy::U32),
+                    Integer::I64 => uint(chalk_ir::UintTy::U64),
+                    Integer::I128 => uint(chalk_ir::UintTy::U128),
                 },
             }),
         })
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 06a42a95d60..9931a7f32ef 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -121,6 +121,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'
                 | ty::PredicateKind::Subtype(..)
                 | ty::PredicateKind::Coerce(..)
                 | ty::PredicateKind::ConstEvaluatable(..)
+                | ty::PredicateKind::Ambiguous
                 | ty::PredicateKind::ConstEquate(..) => bug!("unexpected predicate {}", predicate),
             };
             let value = chalk_ir::ProgramClauseImplication {
@@ -212,6 +213,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predi
             ty::PredicateKind::ClosureKind(..)
             | ty::PredicateKind::Coerce(..)
             | ty::PredicateKind::ConstEvaluatable(..)
+            | ty::PredicateKind::Ambiguous
             | ty::PredicateKind::ConstEquate(..) => {
                 chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner))
             }
@@ -411,7 +413,11 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty<RustInterner<'tcx>> {
             TyKind::Closure(closure, substitution) => {
                 ty::Closure(closure.0, substitution.lower_into(interner))
             }
-            TyKind::Generator(..) => unimplemented!(),
+            TyKind::Generator(generator, substitution) => ty::Generator(
+                generator.0,
+                substitution.lower_into(interner),
+                ast::Movability::Static,
+            ),
             TyKind::GeneratorWitness(..) => unimplemented!(),
             TyKind::Never => ty::Never,
             TyKind::Tuple(_len, substitution) => {
@@ -625,6 +631,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_ir::QuantifiedWhereClause<RustInterner<'
             | ty::PredicateKind::Coerce(..)
             | ty::PredicateKind::ConstEvaluatable(..)
             | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::Ambiguous
             | ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                 bug!("unexpected predicate {}", &self)
             }
@@ -754,6 +761,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_solve::rust_ir::QuantifiedInlineBound<Ru
             | ty::PredicateKind::Coerce(..)
             | ty::PredicateKind::ConstEvaluatable(..)
             | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::Ambiguous
             | ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                 bug!("unexpected predicate {}", &self)
             }
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index 82f6111f6f9..3ab353c9638 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -5,16 +5,15 @@
 use rustc_hir as hir;
 use rustc_infer::infer::canonical::{self, Canonical};
 use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
-use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::query::OutlivesBound;
-use rustc_infer::traits::TraitEngineExt as _;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
 use rustc_span::source_map::DUMMY_SP;
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
 use rustc_trait_selection::traits::wf;
-use rustc_trait_selection::traits::{TraitEngine, TraitEngineExt};
+use rustc_trait_selection::traits::ObligationCtxt;
 use smallvec::{smallvec, SmallVec};
 
 pub(crate) fn provide(p: &mut Providers) {
@@ -30,16 +29,16 @@ fn implied_outlives_bounds<'tcx>(
 > {
     tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| {
         let (param_env, ty) = key.into_parts();
-        compute_implied_outlives_bounds(&ocx.infcx, param_env, ty)
+        compute_implied_outlives_bounds(ocx, param_env, ty)
     })
 }
 
 fn compute_implied_outlives_bounds<'tcx>(
-    infcx: &InferCtxt<'tcx>,
+    ocx: &ObligationCtxt<'_, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     ty: Ty<'tcx>,
 ) -> Fallible<Vec<OutlivesBound<'tcx>>> {
-    let tcx = infcx.tcx;
+    let tcx = ocx.infcx.tcx;
 
     // Sometimes when we ask what it takes for T: WF, we get back that
     // U: WF is required; in that case, we push U onto this stack and
@@ -52,8 +51,6 @@ fn compute_implied_outlives_bounds<'tcx>(
     let mut outlives_bounds: Vec<ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>> =
         vec![];
 
-    let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);
-
     while let Some(arg) = wf_args.pop() {
         if !checked_wf_args.insert(arg) {
             continue;
@@ -70,15 +67,15 @@ fn compute_implied_outlives_bounds<'tcx>(
         // FIXME(@lcnr): It's not really "always fine", having fewer implied
         // bounds can be backward incompatible, e.g. #101951 was caused by
         // us not dealing with inference vars in `TypeOutlives` predicates.
-        let obligations = wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP)
-            .unwrap_or_default();
+        let obligations =
+            wf::obligations(ocx.infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP)
+                .unwrap_or_default();
 
         // While these predicates should all be implied by other parts of
         // the program, they are still relevant as they may constrain
         // inference variables, which is necessary to add the correct
         // implied bounds in some cases, mostly when dealing with projections.
-        fulfill_cx.register_predicate_obligations(
-            infcx,
+        ocx.register_obligations(
             obligations.iter().filter(|o| o.predicate.has_non_region_infer()).cloned(),
         );
 
@@ -97,6 +94,7 @@ fn compute_implied_outlives_bounds<'tcx>(
                     | ty::PredicateKind::ObjectSafe(..)
                     | ty::PredicateKind::ConstEvaluatable(..)
                     | ty::PredicateKind::ConstEquate(..)
+                    | ty::PredicateKind::Ambiguous
                     | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
                     ty::PredicateKind::WellFormed(arg) => {
                         wf_args.push(arg);
@@ -115,9 +113,9 @@ fn compute_implied_outlives_bounds<'tcx>(
         }));
     }
 
-    // Ensure that those obligations that we had to solve
-    // get solved *here*.
-    match fulfill_cx.select_all_or_error(infcx).as_slice() {
+    // This call to `select_all_or_error` is necessary to constrain inference variables, which we
+    // use further down when computing the implied bounds.
+    match ocx.select_all_or_error().as_slice() {
         [] => (),
         _ => return Err(NoSolution),
     }
@@ -129,7 +127,7 @@ fn compute_implied_outlives_bounds<'tcx>(
         .flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() {
             ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)],
             ty::GenericArgKind::Type(ty_a) => {
-                let ty_a = infcx.resolve_vars_if_possible(ty_a);
+                let ty_a = ocx.infcx.resolve_vars_if_possible(ty_a);
                 let mut components = smallvec![];
                 push_outlives_components(tcx, ty_a, &mut components);
                 implied_bounds_from_components(r_b, components)
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index f1835d317e8..5200908527a 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -66,6 +66,7 @@ fn not_outlives_predicate<'tcx>(p: ty::Predicate<'tcx>) -> bool {
         | ty::PredicateKind::Coerce(..)
         | ty::PredicateKind::ConstEvaluatable(..)
         | ty::PredicateKind::ConstEquate(..)
+        | ty::PredicateKind::Ambiguous
         | ty::PredicateKind::TypeWellFormedFromEnv(..) => true,
     }
 }
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
index 5e4ba473061..52fbd3ae047 100644
--- a/compiler/rustc_ty_utils/Cargo.toml
+++ b/compiler/rustc_ty_utils/Cargo.toml
@@ -4,8 +4,6 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
-rand = "0.8.4"
-rand_xoshiro = "0.6.0"
 tracing = "0.1"
 rustc_middle = { path = "../rustc_middle" }
 rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 6436713b388..7f16b2d35e8 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -202,6 +202,12 @@ fn resolve_associated_item<'tcx>(
             )),
             substs: generator_data.substs,
         }),
+        traits::ImplSource::Future(future_data) => Some(Instance {
+            def: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
+                future_data.generator_def_id,
+            )),
+            substs: future_data.substs,
+        }),
         traits::ImplSource::Closure(closure_data) => {
             let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap();
             Instance::resolve_closure(
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 92e8542795f..7a1cc1e9e6d 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -13,13 +13,8 @@ use rustc_span::symbol::Symbol;
 use rustc_span::DUMMY_SP;
 use rustc_target::abi::*;
 
-use std::cmp::{self, Ordering};
+use std::fmt::Debug;
 use std::iter;
-use std::num::NonZeroUsize;
-use std::ops::Bound;
-
-use rand::{seq::SliceRandom, SeedableRng};
-use rand_xoshiro::Xoshiro128StarStar;
 
 use crate::layout_sanity_check::sanity_check_layout;
 
@@ -66,16 +61,6 @@ fn layout_of<'tcx>(
     Ok(layout)
 }
 
-#[derive(Copy, Clone, Debug)]
-enum StructKind {
-    /// A tuple, closure, or univariant which cannot be coerced to unsized.
-    AlwaysSized,
-    /// A univariant, the last field of which may be coerced to unsized.
-    MaybeUnsized,
-    /// A univariant, but with a prefix of an arbitrary size & alignment (e.g., enum tag).
-    Prefixed(Size, Align),
-}
-
 // Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`.
 // This is used to go between `memory_index` (source field order to memory order)
 // and `inverse_memory_index` (memory order to source field order).
@@ -89,40 +74,13 @@ fn invert_mapping(map: &[u32]) -> Vec<u32> {
     inverse
 }
 
-fn scalar_pair<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, a: Scalar, b: Scalar) -> LayoutS<'tcx> {
-    let dl = cx.data_layout();
-    let b_align = b.align(dl);
-    let align = a.align(dl).max(b_align).max(dl.aggregate_align);
-    let b_offset = a.size(dl).align_to(b_align.abi);
-    let size = (b_offset + b.size(dl)).align_to(align.abi);
-
-    // HACK(nox): We iter on `b` and then `a` because `max_by_key`
-    // returns the last maximum.
-    let largest_niche = Niche::from_scalar(dl, b_offset, b)
-        .into_iter()
-        .chain(Niche::from_scalar(dl, Size::ZERO, a))
-        .max_by_key(|niche| niche.available(dl));
-
-    LayoutS {
-        variants: Variants::Single { index: VariantIdx::new(0) },
-        fields: FieldsShape::Arbitrary {
-            offsets: vec![Size::ZERO, b_offset],
-            memory_index: vec![0, 1],
-        },
-        abi: Abi::ScalarPair(a, b),
-        largest_niche,
-        align,
-        size,
-    }
-}
-
 fn univariant_uninterned<'tcx>(
     cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
     ty: Ty<'tcx>,
     fields: &[TyAndLayout<'_>],
     repr: &ReprOptions,
     kind: StructKind,
-) -> Result<LayoutS<'tcx>, LayoutError<'tcx>> {
+) -> Result<LayoutS<VariantIdx>, LayoutError<'tcx>> {
     let dl = cx.data_layout();
     let pack = repr.pack;
     if pack.is_some() && repr.align.is_some() {
@@ -130,208 +88,7 @@ fn univariant_uninterned<'tcx>(
         return Err(LayoutError::Unknown(ty));
     }
 
-    let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
-
-    let mut inverse_memory_index: Vec<u32> = (0..fields.len() as u32).collect();
-
-    let optimize = !repr.inhibit_struct_field_reordering_opt();
-    if optimize {
-        let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
-        let optimizing = &mut inverse_memory_index[..end];
-        let field_align = |f: &TyAndLayout<'_>| {
-            if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi }
-        };
-
-        // If `-Z randomize-layout` was enabled for the type definition we can shuffle
-        // the field ordering to try and catch some code making assumptions about layouts
-        // we don't guarantee
-        if repr.can_randomize_type_layout() {
-            // `ReprOptions.layout_seed` is a deterministic seed that we can use to
-            // randomize field ordering with
-            let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed);
-
-            // Shuffle the ordering of the fields
-            optimizing.shuffle(&mut rng);
-
-            // Otherwise we just leave things alone and actually optimize the type's fields
-        } else {
-            match kind {
-                StructKind::AlwaysSized | StructKind::MaybeUnsized => {
-                    optimizing.sort_by_key(|&x| {
-                        // Place ZSTs first to avoid "interesting offsets",
-                        // especially with only one or two non-ZST fields.
-                        let f = &fields[x as usize];
-                        (!f.is_zst(), cmp::Reverse(field_align(f)))
-                    });
-                }
-
-                StructKind::Prefixed(..) => {
-                    // Sort in ascending alignment so that the layout stays optimal
-                    // regardless of the prefix
-                    optimizing.sort_by_key(|&x| field_align(&fields[x as usize]));
-                }
-            }
-
-            // FIXME(Kixiron): We can always shuffle fields within a given alignment class
-            //                 regardless of the status of `-Z randomize-layout`
-        }
-    }
-
-    // inverse_memory_index holds field indices by increasing memory offset.
-    // That is, if field 5 has offset 0, the first element of inverse_memory_index is 5.
-    // We now write field offsets to the corresponding offset slot;
-    // field 5 with offset 0 puts 0 in offsets[5].
-    // At the bottom of this function, we invert `inverse_memory_index` to
-    // produce `memory_index` (see `invert_mapping`).
-
-    let mut sized = true;
-    let mut offsets = vec![Size::ZERO; fields.len()];
-    let mut offset = Size::ZERO;
-    let mut largest_niche = None;
-    let mut largest_niche_available = 0;
-
-    if let StructKind::Prefixed(prefix_size, prefix_align) = kind {
-        let prefix_align =
-            if let Some(pack) = pack { prefix_align.min(pack) } else { prefix_align };
-        align = align.max(AbiAndPrefAlign::new(prefix_align));
-        offset = prefix_size.align_to(prefix_align);
-    }
-
-    for &i in &inverse_memory_index {
-        let field = fields[i as usize];
-        if !sized {
-            cx.tcx.sess.delay_span_bug(
-                DUMMY_SP,
-                &format!(
-                    "univariant: field #{} of `{}` comes after unsized field",
-                    offsets.len(),
-                    ty
-                ),
-            );
-        }
-
-        if field.is_unsized() {
-            sized = false;
-        }
-
-        // Invariant: offset < dl.obj_size_bound() <= 1<<61
-        let field_align = if let Some(pack) = pack {
-            field.align.min(AbiAndPrefAlign::new(pack))
-        } else {
-            field.align
-        };
-        offset = offset.align_to(field_align.abi);
-        align = align.max(field_align);
-
-        debug!("univariant offset: {:?} field: {:#?}", offset, field);
-        offsets[i as usize] = offset;
-
-        if let Some(mut niche) = field.largest_niche {
-            let available = niche.available(dl);
-            if available > largest_niche_available {
-                largest_niche_available = available;
-                niche.offset += offset;
-                largest_niche = Some(niche);
-            }
-        }
-
-        offset = offset.checked_add(field.size, dl).ok_or(LayoutError::SizeOverflow(ty))?;
-    }
-
-    if let Some(repr_align) = repr.align {
-        align = align.max(AbiAndPrefAlign::new(repr_align));
-    }
-
-    debug!("univariant min_size: {:?}", offset);
-    let min_size = offset;
-
-    // As stated above, inverse_memory_index holds field indices by increasing offset.
-    // This makes it an already-sorted view of the offsets vec.
-    // To invert it, consider:
-    // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0.
-    // Field 5 would be the first element, so memory_index is i:
-    // Note: if we didn't optimize, it's already right.
-
-    let memory_index =
-        if optimize { invert_mapping(&inverse_memory_index) } else { inverse_memory_index };
-
-    let size = min_size.align_to(align.abi);
-    let mut abi = Abi::Aggregate { sized };
-
-    // Unpack newtype ABIs and find scalar pairs.
-    if sized && size.bytes() > 0 {
-        // All other fields must be ZSTs.
-        let mut non_zst_fields = fields.iter().enumerate().filter(|&(_, f)| !f.is_zst());
-
-        match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
-            // We have exactly one non-ZST field.
-            (Some((i, field)), None, None) => {
-                // Field fills the struct and it has a scalar or scalar pair ABI.
-                if offsets[i].bytes() == 0 && align.abi == field.align.abi && size == field.size {
-                    match field.abi {
-                        // For plain scalars, or vectors of them, we can't unpack
-                        // newtypes for `#[repr(C)]`, as that affects C ABIs.
-                        Abi::Scalar(_) | Abi::Vector { .. } if optimize => {
-                            abi = field.abi;
-                        }
-                        // But scalar pairs are Rust-specific and get
-                        // treated as aggregates by C ABIs anyway.
-                        Abi::ScalarPair(..) => {
-                            abi = field.abi;
-                        }
-                        _ => {}
-                    }
-                }
-            }
-
-            // Two non-ZST fields, and they're both scalars.
-            (Some((i, a)), Some((j, b)), None) => {
-                match (a.abi, b.abi) {
-                    (Abi::Scalar(a), Abi::Scalar(b)) => {
-                        // Order by the memory placement, not source order.
-                        let ((i, a), (j, b)) = if offsets[i] < offsets[j] {
-                            ((i, a), (j, b))
-                        } else {
-                            ((j, b), (i, a))
-                        };
-                        let pair = scalar_pair(cx, a, b);
-                        let pair_offsets = match pair.fields {
-                            FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
-                                assert_eq!(memory_index, &[0, 1]);
-                                offsets
-                            }
-                            _ => bug!(),
-                        };
-                        if offsets[i] == pair_offsets[0]
-                            && offsets[j] == pair_offsets[1]
-                            && align == pair.align
-                            && size == pair.size
-                        {
-                            // We can use `ScalarPair` only when it matches our
-                            // already computed layout (including `#[repr(C)]`).
-                            abi = pair.abi;
-                        }
-                    }
-                    _ => {}
-                }
-            }
-
-            _ => {}
-        }
-    }
-
-    if fields.iter().any(|f| f.abi.is_uninhabited()) {
-        abi = Abi::Uninhabited;
-    }
-
-    Ok(LayoutS {
-        variants: Variants::Single { index: VariantIdx::new(0) },
-        fields: FieldsShape::Arbitrary { offsets, memory_index },
-        abi,
-        largest_niche,
-        align,
-        size,
-    })
+    cx.univariant(dl, fields, repr, kind).ok_or(LayoutError::SizeOverflow(ty))
 }
 
 fn layout_of_uncached<'tcx>(
@@ -382,14 +139,7 @@ fn layout_of_uncached<'tcx>(
         }
 
         // The never type.
-        ty::Never => tcx.intern_layout(LayoutS {
-            variants: Variants::Single { index: VariantIdx::new(0) },
-            fields: FieldsShape::Primitive,
-            abi: Abi::Uninhabited,
-            largest_niche: None,
-            align: dl.i8_align,
-            size: Size::ZERO,
-        }),
+        ty::Never => tcx.intern_layout(cx.layout_of_never_type()),
 
         // Potentially-wide pointers.
         ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
@@ -418,7 +168,7 @@ fn layout_of_uncached<'tcx>(
             };
 
             // Effectively a (ptr, meta) tuple.
-            tcx.intern_layout(scalar_pair(cx, data_ptr, metadata))
+            tcx.intern_layout(cx.scalar_pair(data_ptr, metadata))
         }
 
         ty::Dynamic(_, _, ty::DynStar) => {
@@ -426,7 +176,7 @@ fn layout_of_uncached<'tcx>(
             data.valid_range_mut().start = 0;
             let mut vtable = scalar_unit(Pointer);
             vtable.valid_range_mut().start = 1;
-            tcx.intern_layout(scalar_pair(cx, data, vtable))
+            tcx.intern_layout(cx.scalar_pair(data, vtable))
         }
 
         // Arrays and slices.
@@ -655,681 +405,41 @@ fn layout_of_uncached<'tcx>(
                     return Err(LayoutError::Unknown(ty));
                 }
 
-                let mut align =
-                    if def.repr().pack.is_some() { dl.i8_align } else { dl.aggregate_align };
-
-                if let Some(repr_align) = def.repr().align {
-                    align = align.max(AbiAndPrefAlign::new(repr_align));
-                }
-
-                let optimize = !def.repr().inhibit_union_abi_opt();
-                let mut size = Size::ZERO;
-                let mut abi = Abi::Aggregate { sized: true };
-                let index = VariantIdx::new(0);
-                for field in &variants[index] {
-                    assert!(field.is_sized());
-                    align = align.max(field.align);
-
-                    // If all non-ZST fields have the same ABI, forward this ABI
-                    if optimize && !field.is_zst() {
-                        // Discard valid range information and allow undef
-                        let field_abi = match field.abi {
-                            Abi::Scalar(x) => Abi::Scalar(x.to_union()),
-                            Abi::ScalarPair(x, y) => Abi::ScalarPair(x.to_union(), y.to_union()),
-                            Abi::Vector { element: x, count } => {
-                                Abi::Vector { element: x.to_union(), count }
-                            }
-                            Abi::Uninhabited | Abi::Aggregate { .. } => {
-                                Abi::Aggregate { sized: true }
-                            }
-                        };
-
-                        if size == Size::ZERO {
-                            // first non ZST: initialize 'abi'
-                            abi = field_abi;
-                        } else if abi != field_abi {
-                            // different fields have different ABI: reset to Aggregate
-                            abi = Abi::Aggregate { sized: true };
-                        }
-                    }
-
-                    size = cmp::max(size, field.size);
-                }
-
-                if let Some(pack) = def.repr().pack {
-                    align = align.min(AbiAndPrefAlign::new(pack));
-                }
-
-                return Ok(tcx.intern_layout(LayoutS {
-                    variants: Variants::Single { index },
-                    fields: FieldsShape::Union(
-                        NonZeroUsize::new(variants[index].len()).ok_or(LayoutError::Unknown(ty))?,
-                    ),
-                    abi,
-                    largest_niche: None,
-                    align,
-                    size: size.align_to(align.abi),
-                }));
-            }
-
-            // A variant is absent if it's uninhabited and only has ZST fields.
-            // Present uninhabited variants only require space for their fields,
-            // but *not* an encoding of the discriminant (e.g., a tag value).
-            // See issue #49298 for more details on the need to leave space
-            // for non-ZST uninhabited data (mostly partial initialization).
-            let absent = |fields: &[TyAndLayout<'_>]| {
-                let uninhabited = fields.iter().any(|f| f.abi.is_uninhabited());
-                let is_zst = fields.iter().all(|f| f.is_zst());
-                uninhabited && is_zst
-            };
-            let (present_first, present_second) = {
-                let mut present_variants = variants
-                    .iter_enumerated()
-                    .filter_map(|(i, v)| if absent(v) { None } else { Some(i) });
-                (present_variants.next(), present_variants.next())
-            };
-            let present_first = match present_first {
-                Some(present_first) => present_first,
-                // Uninhabited because it has no variants, or only absent ones.
-                None if def.is_enum() => {
-                    return Ok(tcx.layout_of(param_env.and(tcx.types.never))?.layout);
-                }
-                // If it's a struct, still compute a layout so that we can still compute the
-                // field offsets.
-                None => VariantIdx::new(0),
-            };
-
-            let is_struct = !def.is_enum() ||
-                    // Only one variant is present.
-                    (present_second.is_none() &&
-                        // Representation optimizations are allowed.
-                        !def.repr().inhibit_enum_layout_opt());
-            if is_struct {
-                // Struct, or univariant enum equivalent to a struct.
-                // (Typechecking will reject discriminant-sizing attrs.)
-
-                let v = present_first;
-                let kind = if def.is_enum() || variants[v].is_empty() {
-                    StructKind::AlwaysSized
-                } else {
-                    let param_env = tcx.param_env(def.did());
-                    let last_field = def.variant(v).fields.last().unwrap();
-                    let always_sized = tcx.type_of(last_field.did).is_sized(tcx, param_env);
-                    if !always_sized { StructKind::MaybeUnsized } else { StructKind::AlwaysSized }
-                };
-
-                let mut st = univariant_uninterned(cx, ty, &variants[v], &def.repr(), kind)?;
-                st.variants = Variants::Single { index: v };
-
-                if def.is_unsafe_cell() {
-                    let hide_niches = |scalar: &mut _| match scalar {
-                        Scalar::Initialized { value, valid_range } => {
-                            *valid_range = WrappingRange::full(value.size(dl))
-                        }
-                        // Already doesn't have any niches
-                        Scalar::Union { .. } => {}
-                    };
-                    match &mut st.abi {
-                        Abi::Uninhabited => {}
-                        Abi::Scalar(scalar) => hide_niches(scalar),
-                        Abi::ScalarPair(a, b) => {
-                            hide_niches(a);
-                            hide_niches(b);
-                        }
-                        Abi::Vector { element, count: _ } => hide_niches(element),
-                        Abi::Aggregate { sized: _ } => {}
-                    }
-                    st.largest_niche = None;
-                    return Ok(tcx.intern_layout(st));
-                }
-
-                let (start, end) = cx.tcx.layout_scalar_valid_range(def.did());
-                match st.abi {
-                    Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => {
-                        // the asserts ensure that we are not using the
-                        // `#[rustc_layout_scalar_valid_range(n)]`
-                        // attribute to widen the range of anything as that would probably
-                        // result in UB somewhere
-                        // FIXME(eddyb) the asserts are probably not needed,
-                        // as larger validity ranges would result in missed
-                        // optimizations, *not* wrongly assuming the inner
-                        // value is valid. e.g. unions enlarge validity ranges,
-                        // because the values may be uninitialized.
-                        if let Bound::Included(start) = start {
-                            // FIXME(eddyb) this might be incorrect - it doesn't
-                            // account for wrap-around (end < start) ranges.
-                            let valid_range = scalar.valid_range_mut();
-                            assert!(valid_range.start <= start);
-                            valid_range.start = start;
-                        }
-                        if let Bound::Included(end) = end {
-                            // FIXME(eddyb) this might be incorrect - it doesn't
-                            // account for wrap-around (end < start) ranges.
-                            let valid_range = scalar.valid_range_mut();
-                            assert!(valid_range.end >= end);
-                            valid_range.end = end;
-                        }
-
-                        // Update `largest_niche` if we have introduced a larger niche.
-                        let niche = Niche::from_scalar(dl, Size::ZERO, *scalar);
-                        if let Some(niche) = niche {
-                            match st.largest_niche {
-                                Some(largest_niche) => {
-                                    // Replace the existing niche even if they're equal,
-                                    // because this one is at a lower offset.
-                                    if largest_niche.available(dl) <= niche.available(dl) {
-                                        st.largest_niche = Some(niche);
-                                    }
-                                }
-                                None => st.largest_niche = Some(niche),
-                            }
-                        }
-                    }
-                    _ => assert!(
-                        start == Bound::Unbounded && end == Bound::Unbounded,
-                        "nonscalar layout for layout_scalar_valid_range type {:?}: {:#?}",
-                        def,
-                        st,
-                    ),
-                }
-
-                return Ok(tcx.intern_layout(st));
-            }
-
-            // At this point, we have handled all unions and
-            // structs. (We have also handled univariant enums
-            // that allow representation optimization.)
-            assert!(def.is_enum());
-
-            // Until we've decided whether to use the tagged or
-            // niche filling LayoutS, we don't want to intern the
-            // variant layouts, so we can't store them in the
-            // overall LayoutS. Store the overall LayoutS
-            // and the variant LayoutSs here until then.
-            struct TmpLayout<'tcx> {
-                layout: LayoutS<'tcx>,
-                variants: IndexVec<VariantIdx, LayoutS<'tcx>>,
+                return Ok(tcx.intern_layout(
+                    cx.layout_of_union(&def.repr(), &variants).ok_or(LayoutError::Unknown(ty))?,
+                ));
             }
 
-            let calculate_niche_filling_layout =
-                || -> Result<Option<TmpLayout<'tcx>>, LayoutError<'tcx>> {
-                    // The current code for niche-filling relies on variant indices
-                    // instead of actual discriminants, so enums with
-                    // explicit discriminants (RFC #2363) would misbehave.
-                    if def.repr().inhibit_enum_layout_opt()
+            tcx.intern_layout(
+                cx.layout_of_struct_or_enum(
+                    &def.repr(),
+                    &variants,
+                    def.is_enum(),
+                    def.is_unsafe_cell(),
+                    tcx.layout_scalar_valid_range(def.did()),
+                    |min, max| Integer::repr_discr(tcx, ty, &def.repr(), min, max),
+                    def.is_enum()
+                        .then(|| def.discriminants(tcx).map(|(v, d)| (v, d.val as i128)))
+                        .into_iter()
+                        .flatten(),
+                    def.repr().inhibit_enum_layout_opt()
                         || def
                             .variants()
                             .iter_enumerated()
-                            .any(|(i, v)| v.discr != ty::VariantDiscr::Relative(i.as_u32()))
-                    {
-                        return Ok(None);
-                    }
-
-                    if variants.len() < 2 {
-                        return Ok(None);
-                    }
-
-                    let mut align = dl.aggregate_align;
-                    let mut variant_layouts = variants
-                        .iter_enumerated()
-                        .map(|(j, v)| {
-                            let mut st = univariant_uninterned(
-                                cx,
-                                ty,
-                                v,
-                                &def.repr(),
-                                StructKind::AlwaysSized,
-                            )?;
-                            st.variants = Variants::Single { index: j };
-
-                            align = align.max(st.align);
-
-                            Ok(st)
-                        })
-                        .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
-
-                    let largest_variant_index = match variant_layouts
-                        .iter_enumerated()
-                        .max_by_key(|(_i, layout)| layout.size.bytes())
-                        .map(|(i, _layout)| i)
+                            .any(|(i, v)| v.discr != ty::VariantDiscr::Relative(i.as_u32())),
                     {
-                        None => return Ok(None),
-                        Some(i) => i,
-                    };
-
-                    let all_indices = VariantIdx::new(0)..=VariantIdx::new(variants.len() - 1);
-                    let needs_disc = |index: VariantIdx| {
-                        index != largest_variant_index && !absent(&variants[index])
-                    };
-                    let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap()
-                        ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap();
-
-                    let count = niche_variants.size_hint().1.unwrap() as u128;
-
-                    // Find the field with the largest niche
-                    let (field_index, niche, (niche_start, niche_scalar)) = match variants
-                        [largest_variant_index]
-                        .iter()
-                        .enumerate()
-                        .filter_map(|(j, field)| Some((j, field.largest_niche?)))
-                        .max_by_key(|(_, niche)| niche.available(dl))
-                        .and_then(|(j, niche)| Some((j, niche, niche.reserve(cx, count)?)))
-                    {
-                        None => return Ok(None),
-                        Some(x) => x,
-                    };
-
-                    let niche_offset = niche.offset
-                        + variant_layouts[largest_variant_index].fields.offset(field_index);
-                    let niche_size = niche.value.size(dl);
-                    let size = variant_layouts[largest_variant_index].size.align_to(align.abi);
-
-                    let all_variants_fit =
-                        variant_layouts.iter_enumerated_mut().all(|(i, layout)| {
-                            if i == largest_variant_index {
-                                return true;
-                            }
-
-                            layout.largest_niche = None;
-
-                            if layout.size <= niche_offset {
-                                // This variant will fit before the niche.
-                                return true;
-                            }
-
-                            // Determine if it'll fit after the niche.
-                            let this_align = layout.align.abi;
-                            let this_offset = (niche_offset + niche_size).align_to(this_align);
-
-                            if this_offset + layout.size > size {
-                                return false;
-                            }
-
-                            // It'll fit, but we need to make some adjustments.
-                            match layout.fields {
-                                FieldsShape::Arbitrary { ref mut offsets, .. } => {
-                                    for (j, offset) in offsets.iter_mut().enumerate() {
-                                        if !variants[i][j].is_zst() {
-                                            *offset += this_offset;
-                                        }
-                                    }
-                                }
-                                _ => {
-                                    panic!("Layout of fields should be Arbitrary for variants")
-                                }
-                            }
-
-                            // It can't be a Scalar or ScalarPair because the offset isn't 0.
-                            if !layout.abi.is_uninhabited() {
-                                layout.abi = Abi::Aggregate { sized: true };
-                            }
-                            layout.size += this_offset;
-
-                            true
-                        });
-
-                    if !all_variants_fit {
-                        return Ok(None);
-                    }
-
-                    let largest_niche = Niche::from_scalar(dl, niche_offset, niche_scalar);
-
-                    let others_zst = variant_layouts
-                        .iter_enumerated()
-                        .all(|(i, layout)| i == largest_variant_index || layout.size == Size::ZERO);
-                    let same_size = size == variant_layouts[largest_variant_index].size;
-                    let same_align = align == variant_layouts[largest_variant_index].align;
-
-                    let abi = if variant_layouts.iter().all(|v| v.abi.is_uninhabited()) {
-                        Abi::Uninhabited
-                    } else if same_size && same_align && others_zst {
-                        match variant_layouts[largest_variant_index].abi {
-                            // When the total alignment and size match, we can use the
-                            // same ABI as the scalar variant with the reserved niche.
-                            Abi::Scalar(_) => Abi::Scalar(niche_scalar),
-                            Abi::ScalarPair(first, second) => {
-                                // Only the niche is guaranteed to be initialised,
-                                // so use union layouts for the other primitive.
-                                if niche_offset == Size::ZERO {
-                                    Abi::ScalarPair(niche_scalar, second.to_union())
-                                } else {
-                                    Abi::ScalarPair(first.to_union(), niche_scalar)
-                                }
-                            }
-                            _ => Abi::Aggregate { sized: true },
-                        }
-                    } else {
-                        Abi::Aggregate { sized: true }
-                    };
-
-                    let layout = LayoutS {
-                        variants: Variants::Multiple {
-                            tag: niche_scalar,
-                            tag_encoding: TagEncoding::Niche {
-                                untagged_variant: largest_variant_index,
-                                niche_variants,
-                                niche_start,
-                            },
-                            tag_field: 0,
-                            variants: IndexVec::new(),
-                        },
-                        fields: FieldsShape::Arbitrary {
-                            offsets: vec![niche_offset],
-                            memory_index: vec![0],
-                        },
-                        abi,
-                        largest_niche,
-                        size,
-                        align,
-                    };
-
-                    Ok(Some(TmpLayout { layout, variants: variant_layouts }))
-                };
-
-            let niche_filling_layout = calculate_niche_filling_layout()?;
-
-            let (mut min, mut max) = (i128::MAX, i128::MIN);
-            let discr_type = def.repr().discr_type();
-            let bits = Integer::from_attr(cx, discr_type).size().bits();
-            for (i, discr) in def.discriminants(tcx) {
-                if variants[i].iter().any(|f| f.abi.is_uninhabited()) {
-                    continue;
-                }
-                let mut x = discr.val as i128;
-                if discr_type.is_signed() {
-                    // sign extend the raw representation to be an i128
-                    x = (x << (128 - bits)) >> (128 - bits);
-                }
-                if x < min {
-                    min = x;
-                }
-                if x > max {
-                    max = x;
-                }
-            }
-            // We might have no inhabited variants, so pretend there's at least one.
-            if (min, max) == (i128::MAX, i128::MIN) {
-                min = 0;
-                max = 0;
-            }
-            assert!(min <= max, "discriminant range is {}...{}", min, max);
-            let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr(), min, max);
-
-            let mut align = dl.aggregate_align;
-            let mut size = Size::ZERO;
-
-            // We're interested in the smallest alignment, so start large.
-            let mut start_align = Align::from_bytes(256).unwrap();
-            assert_eq!(Integer::for_align(dl, start_align), None);
-
-            // repr(C) on an enum tells us to make a (tag, union) layout,
-            // so we need to grow the prefix alignment to be at least
-            // the alignment of the union. (This value is used both for
-            // determining the alignment of the overall enum, and the
-            // determining the alignment of the payload after the tag.)
-            let mut prefix_align = min_ity.align(dl).abi;
-            if def.repr().c() {
-                for fields in &variants {
-                    for field in fields {
-                        prefix_align = prefix_align.max(field.align.abi);
-                    }
-                }
-            }
-
-            // Create the set of structs that represent each variant.
-            let mut layout_variants = variants
-                .iter_enumerated()
-                .map(|(i, field_layouts)| {
-                    let mut st = univariant_uninterned(
-                        cx,
-                        ty,
-                        &field_layouts,
-                        &def.repr(),
-                        StructKind::Prefixed(min_ity.size(), prefix_align),
-                    )?;
-                    st.variants = Variants::Single { index: i };
-                    // Find the first field we can't move later
-                    // to make room for a larger discriminant.
-                    for field in st.fields.index_by_increasing_offset().map(|j| field_layouts[j]) {
-                        if !field.is_zst() || field.align.abi.bytes() != 1 {
-                            start_align = start_align.min(field.align.abi);
-                            break;
-                        }
-                    }
-                    size = cmp::max(size, st.size);
-                    align = align.max(st.align);
-                    Ok(st)
-                })
-                .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
-
-            // Align the maximum variant size to the largest alignment.
-            size = size.align_to(align.abi);
-
-            if size.bytes() >= dl.obj_size_bound() {
-                return Err(LayoutError::SizeOverflow(ty));
-            }
-
-            let typeck_ity = Integer::from_attr(dl, def.repr().discr_type());
-            if typeck_ity < min_ity {
-                // It is a bug if Layout decided on a greater discriminant size than typeck for
-                // some reason at this point (based on values discriminant can take on). Mostly
-                // because this discriminant will be loaded, and then stored into variable of
-                // type calculated by typeck. Consider such case (a bug): typeck decided on
-                // byte-sized discriminant, but layout thinks we need a 16-bit to store all
-                // discriminant values. That would be a bug, because then, in codegen, in order
-                // to store this 16-bit discriminant into 8-bit sized temporary some of the
-                // space necessary to represent would have to be discarded (or layout is wrong
-                // on thinking it needs 16 bits)
-                bug!(
-                    "layout decided on a larger discriminant type ({:?}) than typeck ({:?})",
-                    min_ity,
-                    typeck_ity
-                );
-                // However, it is fine to make discr type however large (as an optimisation)
-                // after this point – we’ll just truncate the value we load in codegen.
-            }
-
-            // Check to see if we should use a different type for the
-            // discriminant. We can safely use a type with the same size
-            // as the alignment of the first field of each variant.
-            // We increase the size of the discriminant to avoid LLVM copying
-            // padding when it doesn't need to. This normally causes unaligned
-            // load/stores and excessive memcpy/memset operations. By using a
-            // bigger integer size, LLVM can be sure about its contents and
-            // won't be so conservative.
-
-            // Use the initial field alignment
-            let mut ity = if def.repr().c() || def.repr().int.is_some() {
-                min_ity
-            } else {
-                Integer::for_align(dl, start_align).unwrap_or(min_ity)
-            };
-
-            // If the alignment is not larger than the chosen discriminant size,
-            // don't use the alignment as the final size.
-            if ity <= min_ity {
-                ity = min_ity;
-            } else {
-                // Patch up the variants' first few fields.
-                let old_ity_size = min_ity.size();
-                let new_ity_size = ity.size();
-                for variant in &mut layout_variants {
-                    match variant.fields {
-                        FieldsShape::Arbitrary { ref mut offsets, .. } => {
-                            for i in offsets {
-                                if *i <= old_ity_size {
-                                    assert_eq!(*i, old_ity_size);
-                                    *i = new_ity_size;
+                        let param_env = tcx.param_env(def.did());
+                        def.is_struct()
+                            && match def.variants().iter().next().and_then(|x| x.fields.last()) {
+                                Some(last_field) => {
+                                    tcx.type_of(last_field.did).is_sized(tcx, param_env)
                                 }
+                                None => false,
                             }
-                            // We might be making the struct larger.
-                            if variant.size <= old_ity_size {
-                                variant.size = new_ity_size;
-                            }
-                        }
-                        _ => bug!(),
-                    }
-                }
-            }
-
-            let tag_mask = ity.size().unsigned_int_max();
-            let tag = Scalar::Initialized {
-                value: Int(ity, signed),
-                valid_range: WrappingRange {
-                    start: (min as u128 & tag_mask),
-                    end: (max as u128 & tag_mask),
-                },
-            };
-            let mut abi = Abi::Aggregate { sized: true };
-
-            if layout_variants.iter().all(|v| v.abi.is_uninhabited()) {
-                abi = Abi::Uninhabited;
-            } else if tag.size(dl) == size {
-                // Make sure we only use scalar layout when the enum is entirely its
-                // own tag (i.e. it has no padding nor any non-ZST variant fields).
-                abi = Abi::Scalar(tag);
-            } else {
-                // Try to use a ScalarPair for all tagged enums.
-                let mut common_prim = None;
-                let mut common_prim_initialized_in_all_variants = true;
-                for (field_layouts, layout_variant) in iter::zip(&variants, &layout_variants) {
-                    let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else {
-                            bug!();
-                        };
-                    let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst());
-                    let (field, offset) = match (fields.next(), fields.next()) {
-                        (None, None) => {
-                            common_prim_initialized_in_all_variants = false;
-                            continue;
-                        }
-                        (Some(pair), None) => pair,
-                        _ => {
-                            common_prim = None;
-                            break;
-                        }
-                    };
-                    let prim = match field.abi {
-                        Abi::Scalar(scalar) => {
-                            common_prim_initialized_in_all_variants &=
-                                matches!(scalar, Scalar::Initialized { .. });
-                            scalar.primitive()
-                        }
-                        _ => {
-                            common_prim = None;
-                            break;
-                        }
-                    };
-                    if let Some(pair) = common_prim {
-                        // This is pretty conservative. We could go fancier
-                        // by conflating things like i32 and u32, or even
-                        // realising that (u8, u8) could just cohabit with
-                        // u16 or even u32.
-                        if pair != (prim, offset) {
-                            common_prim = None;
-                            break;
-                        }
-                    } else {
-                        common_prim = Some((prim, offset));
-                    }
-                }
-                if let Some((prim, offset)) = common_prim {
-                    let prim_scalar = if common_prim_initialized_in_all_variants {
-                        scalar_unit(prim)
-                    } else {
-                        // Common prim might be uninit.
-                        Scalar::Union { value: prim }
-                    };
-                    let pair = scalar_pair(cx, tag, prim_scalar);
-                    let pair_offsets = match pair.fields {
-                        FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
-                            assert_eq!(memory_index, &[0, 1]);
-                            offsets
-                        }
-                        _ => bug!(),
-                    };
-                    if pair_offsets[0] == Size::ZERO
-                        && pair_offsets[1] == *offset
-                        && align == pair.align
-                        && size == pair.size
-                    {
-                        // We can use `ScalarPair` only when it matches our
-                        // already computed layout (including `#[repr(C)]`).
-                        abi = pair.abi;
-                    }
-                }
-            }
-
-            // If we pick a "clever" (by-value) ABI, we might have to adjust the ABI of the
-            // variants to ensure they are consistent. This is because a downcast is
-            // semantically a NOP, and thus should not affect layout.
-            if matches!(abi, Abi::Scalar(..) | Abi::ScalarPair(..)) {
-                for variant in &mut layout_variants {
-                    // We only do this for variants with fields; the others are not accessed anyway.
-                    // Also do not overwrite any already existing "clever" ABIs.
-                    if variant.fields.count() > 0 && matches!(variant.abi, Abi::Aggregate { .. }) {
-                        variant.abi = abi;
-                        // Also need to bump up the size and alignment, so that the entire value fits in here.
-                        variant.size = cmp::max(variant.size, size);
-                        variant.align.abi = cmp::max(variant.align.abi, align.abi);
-                    }
-                }
-            }
-
-            let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag);
-
-            let tagged_layout = LayoutS {
-                variants: Variants::Multiple {
-                    tag,
-                    tag_encoding: TagEncoding::Direct,
-                    tag_field: 0,
-                    variants: IndexVec::new(),
-                },
-                fields: FieldsShape::Arbitrary { offsets: vec![Size::ZERO], memory_index: vec![0] },
-                largest_niche,
-                abi,
-                align,
-                size,
-            };
-
-            let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants };
-
-            let mut best_layout = match (tagged_layout, niche_filling_layout) {
-                (tl, Some(nl)) => {
-                    // Pick the smaller layout; otherwise,
-                    // pick the layout with the larger niche; otherwise,
-                    // pick tagged as it has simpler codegen.
-                    use Ordering::*;
-                    let niche_size = |tmp_l: &TmpLayout<'_>| {
-                        tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl))
-                    };
-                    match (
-                        tl.layout.size.cmp(&nl.layout.size),
-                        niche_size(&tl).cmp(&niche_size(&nl)),
-                    ) {
-                        (Greater, _) => nl,
-                        (Equal, Less) => nl,
-                        _ => tl,
-                    }
-                }
-                (tl, None) => tl,
-            };
-
-            // Now we can intern the variant layouts and store them in the enum layout.
-            best_layout.layout.variants = match best_layout.layout.variants {
-                Variants::Multiple { tag, tag_encoding, tag_field, .. } => Variants::Multiple {
-                    tag,
-                    tag_encoding,
-                    tag_field,
-                    variants: best_layout
-                        .variants
-                        .into_iter()
-                        .map(|layout| tcx.intern_layout(layout))
-                        .collect(),
-                },
-                _ => bug!(),
-            };
-
-            tcx.intern_layout(best_layout.layout)
+                    },
+                )
+                .ok_or(LayoutError::SizeOverflow(ty))?,
+            )
         }
 
         // Types with no meaningful known layout.
@@ -1639,13 +749,13 @@ fn generator_layout<'tcx>(
 
             size = size.max(variant.size);
             align = align.max(variant.align);
-            Ok(tcx.intern_layout(variant))
+            Ok(variant)
         })
         .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
 
     size = size.align_to(align.abi);
 
-    let abi = if prefix.abi.is_uninhabited() || variants.iter().all(|v| v.abi().is_uninhabited()) {
+    let abi = if prefix.abi.is_uninhabited() || variants.iter().all(|v| v.abi.is_uninhabited()) {
         Abi::Uninhabited
     } else {
         Abi::Aggregate { sized: true }
diff --git a/compiler/rustc_ty_utils/src/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
index ee5e7bc2359..9eb8f684bdb 100644
--- a/compiler/rustc_ty_utils/src/layout_sanity_check.rs
+++ b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
@@ -249,27 +249,27 @@ pub(super) fn sanity_check_layout<'tcx>(
         if let Variants::Multiple { variants, .. } = &layout.variants {
             for variant in variants.iter() {
                 // No nested "multiple".
-                assert!(matches!(variant.variants(), Variants::Single { .. }));
+                assert!(matches!(variant.variants, Variants::Single { .. }));
                 // Variants should have the same or a smaller size as the full thing,
                 // and same for alignment.
-                if variant.size() > layout.size {
+                if variant.size > layout.size {
                     bug!(
                         "Type with size {} bytes has variant with size {} bytes: {layout:#?}",
                         layout.size.bytes(),
-                        variant.size().bytes(),
+                        variant.size.bytes(),
                     )
                 }
-                if variant.align().abi > layout.align.abi {
+                if variant.align.abi > layout.align.abi {
                     bug!(
                         "Type with alignment {} bytes has variant with alignment {} bytes: {layout:#?}",
                         layout.align.abi.bytes(),
-                        variant.align().abi.bytes(),
+                        variant.align.abi.bytes(),
                     )
                 }
                 // Skip empty variants.
-                if variant.size() == Size::ZERO
-                    || variant.fields().count() == 0
-                    || variant.abi().is_uninhabited()
+                if variant.size == Size::ZERO
+                    || variant.fields.count() == 0
+                    || variant.abi.is_uninhabited()
                 {
                     // These are never actually accessed anyway, so we can skip the coherence check
                     // for them. They also fail that check, since they have
@@ -282,7 +282,7 @@ pub(super) fn sanity_check_layout<'tcx>(
                 let scalar_coherent = |s1: Scalar, s2: Scalar| {
                     s1.size(cx) == s2.size(cx) && s1.align(cx) == s2.align(cx)
                 };
-                let abi_coherent = match (layout.abi, variant.abi()) {
+                let abi_coherent = match (layout.abi, variant.abi) {
                     (Abi::Scalar(s1), Abi::Scalar(s2)) => scalar_coherent(s1, s2),
                     (Abi::ScalarPair(a1, b1), Abi::ScalarPair(a2, b2)) => {
                         scalar_coherent(a1, a2) && scalar_coherent(b1, b2)
diff --git a/library/alloc/benches/lib.rs b/library/alloc/benches/lib.rs
index d418965cd2f..b25d63d835b 100644
--- a/library/alloc/benches/lib.rs
+++ b/library/alloc/benches/lib.rs
@@ -5,7 +5,9 @@
 #![feature(iter_next_chunk)]
 #![feature(repr_simd)]
 #![feature(slice_partition_dedup)]
+#![feature(strict_provenance)]
 #![feature(test)]
+#![deny(fuzzy_provenance_casts)]
 
 extern crate test;
 
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 5e13547abcb..96960d43f58 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -82,6 +82,7 @@
 //
 // Lints:
 #![deny(unsafe_op_in_unsafe_fn)]
+#![deny(fuzzy_provenance_casts)]
 #![warn(deprecated_in_future)]
 #![warn(missing_debug_implementations)]
 #![warn(missing_docs)]
diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs
index 9e5123be989..af49826ff30 100644
--- a/library/alloc/tests/boxed.rs
+++ b/library/alloc/tests/boxed.rs
@@ -102,8 +102,18 @@ unsafe impl const Allocator for ConstAllocator {
 
         let new_ptr = self.allocate(new_layout)?;
         if new_layout.size() > 0 {
-            new_ptr.as_mut_ptr().copy_from_nonoverlapping(ptr.as_ptr(), old_layout.size());
-            self.deallocate(ptr, old_layout);
+            // Safety: `new_ptr` is valid for writes and `ptr` for reads of
+            // `old_layout.size()`, because `new_layout.size() >=
+            // old_layout.size()` (which is an invariant that must be upheld by
+            // callers).
+            unsafe {
+                new_ptr.as_mut_ptr().copy_from_nonoverlapping(ptr.as_ptr(), old_layout.size());
+            }
+            // Safety: `ptr` is never used again is also an invariant which must
+            // be upheld by callers.
+            unsafe {
+                self.deallocate(ptr, old_layout);
+            }
         }
         Ok(new_ptr)
     }
@@ -114,12 +124,21 @@ unsafe impl const Allocator for ConstAllocator {
         old_layout: Layout,
         new_layout: Layout,
     ) -> Result<NonNull<[u8]>, AllocError> {
-        let new_ptr = self.grow(ptr, old_layout, new_layout)?;
+        // Safety: Invariants of `grow_zeroed` and `grow` are the same, and must
+        // be enforced by callers.
+        let new_ptr = unsafe { self.grow(ptr, old_layout, new_layout)? };
         if new_layout.size() > 0 {
             let old_size = old_layout.size();
             let new_size = new_layout.size();
             let raw_ptr = new_ptr.as_mut_ptr();
-            raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
+            // Safety:
+            // - `grow` returned Ok, so the returned pointer must be valid for
+            //   `new_size` bytes
+            // - `new_size` must be larger than `old_size`, which is an
+            //   invariant which must be upheld by callers.
+            unsafe {
+                raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
+            }
         }
         Ok(new_ptr)
     }
@@ -137,8 +156,18 @@ unsafe impl const Allocator for ConstAllocator {
 
         let new_ptr = self.allocate(new_layout)?;
         if new_layout.size() > 0 {
-            new_ptr.as_mut_ptr().copy_from_nonoverlapping(ptr.as_ptr(), new_layout.size());
-            self.deallocate(ptr, old_layout);
+            // Safety: `new_ptr` and `ptr` are valid for reads/writes of
+            // `new_layout.size()` because of the invariants of shrink, which
+            // include `new_layout.size()` being smaller than (or equal to)
+            // `old_layout.size()`.
+            unsafe {
+                new_ptr.as_mut_ptr().copy_from_nonoverlapping(ptr.as_ptr(), new_layout.size());
+            }
+            // Safety: `ptr` is never used again is also an invariant which must
+            // be upheld by callers.
+            unsafe {
+                self.deallocate(ptr, old_layout);
+            }
         }
         Ok(new_ptr)
     }
diff --git a/library/alloc/tests/fmt.rs b/library/alloc/tests/fmt.rs
index 5ee6db43fda..04da95bbb83 100644
--- a/library/alloc/tests/fmt.rs
+++ b/library/alloc/tests/fmt.rs
@@ -2,6 +2,7 @@
 
 use std::cell::RefCell;
 use std::fmt::{self, Write};
+use std::ptr;
 
 #[test]
 fn test_format() {
@@ -76,14 +77,14 @@ fn test_format_macro_interface() {
     t!(format!("{}", "foo"), "foo");
     t!(format!("{}", "foo".to_string()), "foo");
     if cfg!(target_pointer_width = "32") {
-        t!(format!("{:#p}", 0x1234 as *const isize), "0x00001234");
-        t!(format!("{:#p}", 0x1234 as *mut isize), "0x00001234");
+        t!(format!("{:#p}", ptr::invalid::<isize>(0x1234)), "0x00001234");
+        t!(format!("{:#p}", ptr::invalid_mut::<isize>(0x1234)), "0x00001234");
     } else {
-        t!(format!("{:#p}", 0x1234 as *const isize), "0x0000000000001234");
-        t!(format!("{:#p}", 0x1234 as *mut isize), "0x0000000000001234");
+        t!(format!("{:#p}", ptr::invalid::<isize>(0x1234)), "0x0000000000001234");
+        t!(format!("{:#p}", ptr::invalid_mut::<isize>(0x1234)), "0x0000000000001234");
     }
-    t!(format!("{:p}", 0x1234 as *const isize), "0x1234");
-    t!(format!("{:p}", 0x1234 as *mut isize), "0x1234");
+    t!(format!("{:p}", ptr::invalid::<isize>(0x1234)), "0x1234");
+    t!(format!("{:p}", ptr::invalid_mut::<isize>(0x1234)), "0x1234");
     t!(format!("{A:x}"), "aloha");
     t!(format!("{B:X}"), "adios");
     t!(format!("foo {} ☃☃☃☃☃☃", "bar"), "foo bar ☃☃☃☃☃☃");
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index ffc5ca7a5c6..d6d2b055b23 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -47,6 +47,8 @@
 #![feature(strict_provenance)]
 #![feature(once_cell)]
 #![feature(drain_keep_rest)]
+#![deny(fuzzy_provenance_casts)]
+#![deny(unsafe_op_in_unsafe_fn)]
 
 use std::collections::hash_map::DefaultHasher;
 use std::hash::{Hash, Hasher};
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index 9689196ef21..4d182be02c9 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -1632,6 +1632,18 @@ fn strslice_issue_16878() {
 }
 
 #[test]
+fn strslice_issue_104726() {
+    // Edge-case in the simd_contains impl.
+    // The first and last byte are the same so it backtracks by one byte
+    // which aligns with the end of the string. Previously incorrect offset calculations
+    // lead to out-of-bounds slicing.
+    #[rustfmt::skip]
+    let needle =                        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaba";
+    let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab";
+    assert!(!haystack.contains(needle));
+}
+
+#[test]
 #[cfg_attr(miri, ignore)] // Miri is too slow
 fn test_strslice_contains() {
     let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index e0271187044..7ebed0d5ca6 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -1089,7 +1089,8 @@ fn test_into_iter_drop_allocator() {
         }
 
         unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
-            System.deallocate(ptr, layout)
+            // Safety: Invariants passed to caller.
+            unsafe { System.deallocate(ptr, layout) }
         }
     }
 
diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs
index 107cf92c1c0..f2b961d62e0 100644
--- a/library/core/src/future/mod.rs
+++ b/library/core/src/future/mod.rs
@@ -9,12 +9,8 @@
 //! [`await`]: ../../std/keyword.await.html
 //! [async book]: https://rust-lang.github.io/async-book/
 
-use crate::{
-    ops::{Generator, GeneratorState},
-    pin::Pin,
-    ptr::NonNull,
-    task::{Context, Poll},
-};
+use crate::ptr::NonNull;
+use crate::task::Context;
 
 mod future;
 mod into_future;
@@ -48,6 +44,7 @@ pub use poll_fn::{poll_fn, PollFn};
 ///    non-Send/Sync as well, and we don't want that.
 ///
 /// It also simplifies the HIR lowering of `.await`.
+#[cfg_attr(not(bootstrap), lang = "ResumeTy")]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 #[derive(Debug, Copy, Clone)]
@@ -64,15 +61,21 @@ unsafe impl Sync for ResumeTy {}
 /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
 /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
 // This is `const` to avoid extra errors after we recover from `const async fn`
-#[lang = "from_generator"]
+#[cfg_attr(bootstrap, lang = "from_generator")]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 #[rustc_const_unstable(feature = "gen_future", issue = "50547")]
 #[inline]
 pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
 where
-    T: Generator<ResumeTy, Yield = ()>,
+    T: crate::ops::Generator<ResumeTy, Yield = ()>,
 {
+    use crate::{
+        ops::{Generator, GeneratorState},
+        pin::Pin,
+        task::Poll,
+    };
+
     #[rustc_diagnostic_item = "gen_future"]
     struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
 
@@ -109,3 +112,11 @@ pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> {
     // that fulfills all the requirements for a mutable reference.
     unsafe { &mut *cx.0.as_ptr().cast() }
 }
+
+#[cfg_attr(not(bootstrap), lang = "identity_future")]
+#[doc(hidden)]
+#[unstable(feature = "gen_future", issue = "50547")]
+#[inline]
+pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
+    f
+}
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 331714a993c..d6e9da187e8 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1493,11 +1493,13 @@ mod prim_ref {}
 /// However, a direct cast back is not possible. You need to use `transmute`:
 ///
 /// ```rust
+/// # #[cfg(not(miri))] { // FIXME: use strict provenance APIs once they are stable, then remove this `cfg`
 /// # let fnptr: fn(i32) -> i32 = |x| x+2;
 /// # let fnptr_addr = fnptr as usize;
 /// let fnptr = fnptr_addr as *const ();
 /// let fnptr: fn(i32) -> i32 = unsafe { std::mem::transmute(fnptr) };
 /// assert_eq!(fnptr(40), 42);
+/// # }
 /// ```
 ///
 /// Crucially, we `as`-cast to a raw pointer before `transmute`ing to a function pointer.
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 969029e262e..76603e1018d 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -112,11 +112,13 @@ impl<T: ?Sized> *const T {
     ///
     /// ```
     /// #![feature(ptr_to_from_bits)]
+    /// # #[cfg(not(miri))] { // doctest does not work with strict provenance
     /// let array = [13, 42];
     /// let p0: *const i32 = &array[0];
     /// assert_eq!(<*const _>::from_bits(p0.to_bits()), p0);
     /// let p1: *const i32 = &array[1];
     /// assert_eq!(p1.to_bits() - p0.to_bits(), 4);
+    /// # }
     /// ```
     #[unstable(feature = "ptr_to_from_bits", issue = "91126")]
     #[deprecated(
@@ -140,9 +142,11 @@ impl<T: ?Sized> *const T {
     ///
     /// ```
     /// #![feature(ptr_to_from_bits)]
+    /// # #[cfg(not(miri))] { // doctest does not work with strict provenance
     /// use std::ptr::NonNull;
     /// let dangling: *const u8 = NonNull::dangling().as_ptr();
     /// assert_eq!(<*const u8>::from_bits(1), dangling);
+    /// # }
     /// ```
     #[unstable(feature = "ptr_to_from_bits", issue = "91126")]
     #[deprecated(
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index d1b3a634433..b03cad18e4a 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -117,12 +117,14 @@ impl<T: ?Sized> *mut T {
     ///
     /// ```
     /// #![feature(ptr_to_from_bits)]
+    /// # #[cfg(not(miri))] { // doctest does not work with strict provenance
     /// let mut array = [13, 42];
     /// let mut it = array.iter_mut();
     /// let p0: *mut i32 = it.next().unwrap();
     /// assert_eq!(<*mut _>::from_bits(p0.to_bits()), p0);
     /// let p1: *mut i32 = it.next().unwrap();
     /// assert_eq!(p1.to_bits() - p0.to_bits(), 4);
+    /// }
     /// ```
     #[unstable(feature = "ptr_to_from_bits", issue = "91126")]
     #[deprecated(
@@ -146,9 +148,11 @@ impl<T: ?Sized> *mut T {
     ///
     /// ```
     /// #![feature(ptr_to_from_bits)]
+    /// # #[cfg(not(miri))] { // doctest does not work with strict provenance
     /// use std::ptr::NonNull;
     /// let dangling: *mut u8 = NonNull::dangling().as_ptr();
     /// assert_eq!(<*mut u8>::from_bits(1), dangling);
+    /// }
     /// ```
     #[unstable(feature = "ptr_to_from_bits", issue = "91126")]
     #[deprecated(
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index fbc0fc397a5..c0167388713 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -902,6 +902,12 @@ impl str {
     ///
     /// assert_eq!(None, iter.next());
     /// ```
+    ///
+    /// If the string is empty or all whitespace, the iterator yields no string slices:
+    /// ```
+    /// assert_eq!("".split_whitespace().next(), None);
+    /// assert_eq!("   ".split_whitespace().next(), None);
+    /// ```
     #[must_use = "this returns the split string as an iterator, \
                   without modifying the original"]
     #[stable(feature = "split_whitespace", since = "1.1.0")]
@@ -946,6 +952,12 @@ impl str {
     ///
     /// assert_eq!(None, iter.next());
     /// ```
+    ///
+    /// If the string is empty or all ASCII whitespace, the iterator yields no string slices:
+    /// ```
+    /// assert_eq!("".split_ascii_whitespace().next(), None);
+    /// assert_eq!("   ".split_ascii_whitespace().next(), None);
+    /// ```
     #[must_use = "this returns the split string as an iterator, \
                   without modifying the original"]
     #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs
index c5be32861f9..d76d6f8b2a2 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -1741,6 +1741,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option<bool> {
     use crate::simd::{SimdPartialEq, ToBitMask};
 
     let first_probe = needle[0];
+    let last_byte_offset = needle.len() - 1;
 
     // the offset used for the 2nd vector
     let second_probe_offset = if needle.len() == 2 {
@@ -1758,7 +1759,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option<bool> {
     };
 
     // do a naive search if the haystack is too small to fit
-    if haystack.len() < Block::LANES + second_probe_offset {
+    if haystack.len() < Block::LANES + last_byte_offset {
         return Some(haystack.windows(needle.len()).any(|c| c == needle));
     }
 
@@ -1815,7 +1816,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option<bool> {
     // The loop condition must ensure that there's enough headroom to read LANE bytes,
     // and not only at the current index but also at the index shifted by block_offset
     const UNROLL: usize = 4;
-    while i + second_probe_offset + UNROLL * Block::LANES < haystack.len() && !result {
+    while i + last_byte_offset + UNROLL * Block::LANES < haystack.len() && !result {
         let mut masks = [0u16; UNROLL];
         for j in 0..UNROLL {
             masks[j] = test_chunk(i + j * Block::LANES);
@@ -1828,7 +1829,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option<bool> {
         }
         i += UNROLL * Block::LANES;
     }
-    while i + second_probe_offset + Block::LANES < haystack.len() && !result {
+    while i + last_byte_offset + Block::LANES < haystack.len() && !result {
         let mask = test_chunk(i);
         if mask != 0 {
             result |= check_mask(i, mask, result);
@@ -1840,7 +1841,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option<bool> {
     // This simply repeats the same procedure but as right-aligned chunk instead
     // of a left-aligned one. The last byte must be exactly flush with the string end so
     // we don't miss a single byte or read out of bounds.
-    let i = haystack.len() - second_probe_offset - Block::LANES;
+    let i = haystack.len() - last_byte_offset - Block::LANES;
     let mask = test_chunk(i);
     if mask != 0 {
         result |= check_mask(i, mask, result);
@@ -1860,6 +1861,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option<bool> {
 #[cfg(all(target_arch = "x86_64", target_feature = "sse2"))] // only called on x86
 #[inline]
 unsafe fn small_slice_eq(x: &[u8], y: &[u8]) -> bool {
+    debug_assert_eq!(x.len(), y.len());
     // This function is adapted from
     // https://github.com/BurntSushi/memchr/blob/8037d11b4357b0f07be2bb66dc2659d9cf28ad32/src/memmem/util.rs#L32
 
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 41f0a25dbc3..f1dc4f7b575 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -9,6 +9,7 @@ use crate::task::Ready;
 /// scheduled to receive a wakeup instead.
 #[must_use = "this `Poll` may be a `Pending` variant, which should be handled"]
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
+#[cfg_attr(not(bootstrap), lang = "Poll")]
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub enum Poll<T> {
     /// Represents that a value is immediately ready.
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 63ee6c521d7..65d4c3c891e 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -220,6 +220,7 @@
 #![allow(explicit_outlives_requirements)]
 #![allow(unused_lifetimes)]
 #![deny(rustc::existing_doc_keyword)]
+#![deny(fuzzy_provenance_casts)]
 // Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind`
 #![deny(ffi_unwind_calls)]
 // std may use features in a platform-specific way
@@ -598,7 +599,7 @@ mod panicking;
 mod personality;
 
 #[path = "../../backtrace/src/lib.rs"]
-#[allow(dead_code, unused_attributes)]
+#[allow(dead_code, unused_attributes, fuzzy_provenance_casts)]
 mod backtrace_rs;
 
 // Re-export macros defined in libcore.
diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs
index 72cb3406dca..5c1634084a0 100644
--- a/library/std/src/os/windows/io/socket.rs
+++ b/library/std/src/os/windows/io/socket.rs
@@ -90,6 +90,7 @@ impl OwnedSocket {
     }
 
     // FIXME(strict_provenance_magic): we defined RawSocket to be a u64 ;-;
+    #[allow(fuzzy_provenance_casts)]
     #[cfg(not(target_vendor = "uwp"))]
     pub(crate) fn set_no_inherit(&self) -> io::Result<()> {
         cvt(unsafe {
diff --git a/library/std/src/personality/dwarf/eh.rs b/library/std/src/personality/dwarf/eh.rs
index 27b50c13b77..a783e187004 100644
--- a/library/std/src/personality/dwarf/eh.rs
+++ b/library/std/src/personality/dwarf/eh.rs
@@ -13,6 +13,7 @@
 
 use super::DwarfReader;
 use core::mem;
+use core::ptr;
 
 pub const DW_EH_PE_omit: u8 = 0xFF;
 pub const DW_EH_PE_absptr: u8 = 0x00;
@@ -151,7 +152,7 @@ unsafe fn read_encoded_pointer(
 
     // DW_EH_PE_aligned implies it's an absolute pointer value
     if encoding == DW_EH_PE_aligned {
-        reader.ptr = round_up(reader.ptr as usize, mem::size_of::<usize>())? as *const u8;
+        reader.ptr = reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::<usize>())?);
         return Ok(reader.read::<usize>());
     }
 
@@ -171,7 +172,7 @@ unsafe fn read_encoded_pointer(
     result += match encoding & 0x70 {
         DW_EH_PE_absptr => 0,
         // relative to address of the encoded value, despite the name
-        DW_EH_PE_pcrel => reader.ptr as usize,
+        DW_EH_PE_pcrel => reader.ptr.expose_addr(),
         DW_EH_PE_funcrel => {
             if context.func_start == 0 {
                 return Err(());
@@ -184,7 +185,7 @@ unsafe fn read_encoded_pointer(
     };
 
     if encoding & DW_EH_PE_indirect != 0 {
-        result = *(result as *const usize);
+        result = *ptr::from_exposed_addr::<usize>(result);
     }
 
     Ok(result)
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 331714a993c..d6e9da187e8 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -1493,11 +1493,13 @@ mod prim_ref {}
 /// However, a direct cast back is not possible. You need to use `transmute`:
 ///
 /// ```rust
+/// # #[cfg(not(miri))] { // FIXME: use strict provenance APIs once they are stable, then remove this `cfg`
 /// # let fnptr: fn(i32) -> i32 = |x| x+2;
 /// # let fnptr_addr = fnptr as usize;
 /// let fnptr = fnptr_addr as *const ();
 /// let fnptr: fn(i32) -> i32 = unsafe { std::mem::transmute(fnptr) };
 /// assert_eq!(fnptr(40), 42);
+/// # }
 /// ```
 ///
 /// Crucially, we `as`-cast to a raw pointer before `transmute`ing to a function pointer.
diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs
index b1d32929ecf..01e4ffe3dfc 100644
--- a/library/std/src/sys/sgx/mod.rs
+++ b/library/std/src/sys/sgx/mod.rs
@@ -3,6 +3,7 @@
 //! This module contains the facade (aka platform-specific) implementations of
 //! OS level functionality for Fortanix SGX.
 #![deny(unsafe_op_in_unsafe_fn)]
+#![allow(fuzzy_provenance_casts)] // FIXME: this entire module systematically confuses pointers and integers
 
 use crate::io::ErrorKind;
 use crate::sync::atomic::{AtomicBool, Ordering};
diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index a218910f0ec..0fa11f3761a 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -27,7 +27,10 @@ pub type _Unwind_Trace_Fn =
 #[cfg(target_arch = "x86")]
 pub const unwinder_private_data_size: usize = 5;
 
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", not(target_os = "windows")))]
+pub const unwinder_private_data_size: usize = 2;
+
+#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
 pub const unwinder_private_data_size: usize = 6;
 
 #[cfg(all(target_arch = "arm", not(any(target_os = "ios", target_os = "watchos"))))]
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 0cd778a0cbb..fe8a028dfd3 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -225,13 +225,13 @@ dependencies = [
 
 [[package]]
 name = "fd-lock"
-version = "3.0.7"
+version = "3.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c93a581058d957dc4176875aad04f82f81613e6611d64aa1a9c755bdfb16711"
+checksum = "bb21c69b9fea5e15dbc1049e4b77145dd0ba1c84019c488102de0dc4ea4b0a27"
 dependencies = [
  "cfg-if",
  "rustix",
- "windows-sys 0.42.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -319,9 +319,13 @@ dependencies = [
 
 [[package]]
 name = "io-lifetimes"
-version = "0.7.2"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24c3f4eff5495aee4c0399d7b6a0dc2b6e81be84242ffbfcf253ebacccc1d0cb"
+checksum = "a7d367024b3f3414d8e01f437f704f41a9f64ab36f9067fa73e526ad4c763c87"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
 
 [[package]]
 name = "itoa"
@@ -337,15 +341,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.126"
+version = "0.2.137"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
+checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.0.46"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d"
+checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
 
 [[package]]
 name = "log"
@@ -529,16 +533,16 @@ checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
 
 [[package]]
 name = "rustix"
-version = "0.35.6"
+version = "0.36.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef258c11e17f5c01979a10543a30a4e12faef6aab217a74266e747eefa3aed88"
+checksum = "0b1fbb4dfc4eb1d390c02df47760bb19a84bb80b301ecc947ab5406394d8223e"
 dependencies = [
  "bitflags",
  "errno",
  "io-lifetimes",
  "libc",
  "linux-raw-sys",
- "windows-sys 0.36.1",
+ "windows-sys",
 ]
 
 [[package]]
@@ -727,30 +731,17 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
 name = "windows-sys"
-version = "0.36.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
-dependencies = [
- "windows_aarch64_msvc 0.36.1",
- "windows_i686_gnu 0.36.1",
- "windows_i686_msvc 0.36.1",
- "windows_x86_64_gnu 0.36.1",
- "windows_x86_64_msvc 0.36.1",
-]
-
-[[package]]
-name = "windows-sys"
 version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
 dependencies = [
  "windows_aarch64_gnullvm",
- "windows_aarch64_msvc 0.42.0",
- "windows_i686_gnu 0.42.0",
- "windows_i686_msvc 0.42.0",
- "windows_x86_64_gnu 0.42.0",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
  "windows_x86_64_gnullvm",
- "windows_x86_64_msvc 0.42.0",
+ "windows_x86_64_msvc",
 ]
 
 [[package]]
@@ -761,48 +752,24 @@ checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.36.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
-
-[[package]]
-name = "windows_aarch64_msvc"
 version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.36.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
-
-[[package]]
-name = "windows_i686_gnu"
 version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.36.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
-
-[[package]]
-name = "windows_i686_msvc"
 version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.36.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
-
-[[package]]
-name = "windows_x86_64_gnu"
 version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
@@ -815,12 +782,6 @@ checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.36.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
-
-[[package]]
-name = "windows_x86_64_msvc"
 version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 4c24c214d2c..8751a71caf1 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -36,7 +36,7 @@ test = false
 
 [dependencies]
 cmake = "0.1.38"
-fd-lock = "3.0.7"
+fd-lock = "3.0.8"
 filetime = "0.2"
 getopts = "0.2.19"
 cc = "1.0.69"
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 8d999302a6d..251431a15eb 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1094,7 +1094,13 @@ impl<'a> Builder<'a> {
             let my_out = match mode {
                 // This is the intended out directory for compiler documentation.
                 Mode::Rustc | Mode::ToolRustc => self.compiler_doc_out(target),
-                Mode::Std => out_dir.join(target.triple).join("doc"),
+                Mode::Std => {
+                    if self.config.cmd.json() {
+                        out_dir.join(target.triple).join("json-doc")
+                    } else {
+                        out_dir.join(target.triple).join("doc")
+                    }
+                }
                 _ => panic!("doc mode {:?} not expected", mode),
             };
             let rustdoc = self.rustdoc(compiler);
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 2fef7f65827..a274d7b9aa1 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1191,7 +1191,6 @@ impl Step for Clippy {
 
         let mut tarball = Tarball::new(builder, "clippy", &target.triple);
         tarball.set_overlay(OverlayKind::Clippy);
-        tarball.is_preview(true);
         tarball.add_file(clippy, "bin", 0o755);
         tarball.add_file(cargoclippy, "bin", 0o755);
         tarball.add_legal_and_readme_to("share/doc/clippy");
@@ -1289,7 +1288,6 @@ impl Step for Rustfmt {
             .expect("cargo fmt expected to build - essential tool");
         let mut tarball = Tarball::new(builder, "rustfmt", &target.triple);
         tarball.set_overlay(OverlayKind::Rustfmt);
-        tarball.is_preview(true);
         tarball.add_file(rustfmt, "bin", 0o755);
         tarball.add_file(cargofmt, "bin", 0o755);
         tarball.add_legal_and_readme_to("share/doc/rustfmt");
@@ -1550,8 +1548,6 @@ impl Step for Extended {
                     format!("{}-{}", name, target.triple)
                 } else if name == "rust-analyzer" {
                     "rust-analyzer-preview".to_string()
-                } else if name == "clippy" {
-                    "clippy-preview".to_string()
                 } else if name == "rust-demangler" {
                     "rust-demangler-preview".to_string()
                 } else if name == "miri" {
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 3180a12c85b..571396eb835 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -564,27 +564,22 @@ fn doc_std(
         );
     }
     let compiler = builder.compiler(stage, builder.config.build);
+
+    let target_doc_dir_name = if format == DocumentationFormat::JSON { "json-doc" } else { "doc" };
+    let target_dir =
+        builder.stage_out(compiler, Mode::Std).join(target.triple).join(target_doc_dir_name);
+
     // This is directory where the compiler will place the output of the command.
     // We will then copy the files from this directory into the final `out` directory, the specified
     // as a function parameter.
-    let out_dir = builder.stage_out(compiler, Mode::Std).join(target.triple).join("doc");
-    // `cargo` uses the same directory for both JSON docs and HTML docs.
-    // This could lead to cross-contamination when copying files into the specified `out` directory.
-    // For example:
-    // ```bash
-    // x doc std
-    // x doc std --json
-    // ```
-    // could lead to HTML docs being copied into the JSON docs output directory.
-    // To avoid this issue, we clean the doc folder before invoking `cargo`.
-    if out_dir.exists() {
-        builder.remove_dir(&out_dir);
-    }
+    let out_dir = target_dir.join(target.triple).join("doc");
 
     let run_cargo_rustdoc_for = |package: &str| {
         let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "rustdoc");
         compile::std_cargo(builder, target, compiler.stage, &mut cargo);
         cargo
+            .arg("--target-dir")
+            .arg(&*target_dir.to_string_lossy())
             .arg("-p")
             .arg(package)
             .arg("-Zskip-rustdoc-fingerprint")
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index d0f389df973..430b3496d00 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -326,6 +326,8 @@ impl Config {
         }
 
         let filename = format!("rustfmt-{version}-{build}.tar.xz", build = host.triple);
+        // cfg(bootstrap): will need to be changed from `rustfmt-preview` to `rustfmt` the next time you run `bump-stage0`.
+        // See <https://github.com/rust-lang/rust/pull/103648>
         self.download_component(DownloadSource::Dist, filename, "rustfmt-preview", &date, "stage0");
 
         self.fix_bin_or_dylib(&bin_root.join("bin").join("rustfmt"));
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 28929acb9b4..27e911c6be5 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -283,6 +283,7 @@ target | std | host | notes
 `powerpc64-wrs-vxworks` | ? |  |
 `powerpc64le-unknown-linux-musl` | ? |  |
 [`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64
+`powerpc64-ibm-aix` | ? |  | 64-bit AIX (7.2 and newer)
 `riscv32gc-unknown-linux-gnu` |   |   | RISC-V Linux (kernel 5.4, glibc 2.33)
 `riscv32gc-unknown-linux-musl` |   |   | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches)
 `riscv32im-unknown-none-elf` | * |  | Bare RISC-V (RV32IM ISA)
diff --git a/src/doc/unstable-book/src/language-features/abi-efiapi.md b/src/doc/unstable-book/src/language-features/abi-efiapi.md
new file mode 100644
index 00000000000..11ef0cfdb14
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/abi-efiapi.md
@@ -0,0 +1,23 @@
+# `abi_efiapi`
+
+The tracking issue for this feature is: [#65815]
+
+[#65815]: https://github.com/rust-lang/rust/issues/65815
+
+------------------------
+
+The `efiapi` calling convention can be used for defining a function with
+an ABI compatible with the UEFI Interfaces as defined in the [UEFI
+Specification].
+
+Example:
+
+```rust
+#![feature(abi_efiapi)]
+
+extern "efiapi" { fn f1(); }
+
+extern "efiapi" fn f2() { todo!() }
+```
+
+[UEFI Specification]: https://uefi.org/specs/UEFI/2.10/
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 3fc4aae923a..e7c3e5a45e8 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -276,7 +276,7 @@ fn build_struct(cx: &mut DocContext<'_>, did: DefId) -> clean::Struct {
     let variant = cx.tcx.adt_def(did).non_enum_variant();
 
     clean::Struct {
-        struct_type: variant.ctor_kind,
+        ctor_kind: variant.ctor_kind(),
         generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates),
         fields: variant.fields.iter().map(|x| clean_middle_field(x, cx)).collect(),
     }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index c20595614b0..b5d4ab55b4a 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -318,6 +318,7 @@ pub(crate) fn clean_predicate<'tcx>(
         | ty::PredicateKind::ObjectSafe(..)
         | ty::PredicateKind::ClosureKind(..)
         | ty::PredicateKind::ConstEquate(..)
+        | ty::PredicateKind::Ambiguous
         | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"),
     }
 }
@@ -1842,16 +1843,16 @@ pub(crate) fn clean_field_with_def_id(
 }
 
 pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocContext<'tcx>) -> Item {
-    let kind = match variant.ctor_kind {
-        CtorKind::Const => Variant::CLike(match variant.discr {
+    let kind = match variant.ctor_kind() {
+        Some(CtorKind::Const) => Variant::CLike(match variant.discr {
             ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }),
             ty::VariantDiscr::Relative(_) => None,
         }),
-        CtorKind::Fn => Variant::Tuple(
+        Some(CtorKind::Fn) => Variant::Tuple(
             variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
         ),
-        CtorKind::Fictive => Variant::Struct(VariantStruct {
-            struct_type: CtorKind::Fictive,
+        None => Variant::Struct(VariantStruct {
+            ctor_kind: None,
             fields: variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
         }),
     };
@@ -1865,7 +1866,7 @@ fn clean_variant_data<'tcx>(
 ) -> Variant {
     match variant {
         hir::VariantData::Struct(..) => Variant::Struct(VariantStruct {
-            struct_type: CtorKind::from_hir(variant),
+            ctor_kind: None,
             fields: variant.fields().iter().map(|x| clean_field(x, cx)).collect(),
         }),
         hir::VariantData::Tuple(..) => {
@@ -2060,7 +2061,7 @@ fn clean_maybe_renamed_item<'tcx>(
                 fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
             }),
             ItemKind::Struct(ref variant_data, generics) => StructItem(Struct {
-                struct_type: CtorKind::from_hir(variant_data),
+                ctor_kind: variant_data.ctor_kind(),
                 generics: clean_generics(generics, cx),
                 fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
             }),
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 3d13f7463cb..340d6d7df18 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -2081,7 +2081,7 @@ impl From<hir::PrimTy> for PrimitiveType {
 
 #[derive(Clone, Debug)]
 pub(crate) struct Struct {
-    pub(crate) struct_type: CtorKind,
+    pub(crate) ctor_kind: Option<CtorKind>,
     pub(crate) generics: Generics,
     pub(crate) fields: Vec<Item>,
 }
@@ -2109,7 +2109,7 @@ impl Union {
 /// only as a variant in an enum.
 #[derive(Clone, Debug)]
 pub(crate) struct VariantStruct {
-    pub(crate) struct_type: CtorKind,
+    pub(crate) ctor_kind: Option<CtorKind>,
     pub(crate) fields: Vec<Item>,
 }
 
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 647eb69d9a6..ef28e2a855a 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1071,7 +1071,7 @@ fn write_impl_section_heading(w: &mut Buffer, title: &str, id: &str) {
         w,
         "<h2 id=\"{id}\" class=\"small-section-header\">\
             {title}\
-            <a href=\"#{id}\" class=\"anchor\"></a>\
+            <a href=\"#{id}\" class=\"anchor\">§</a>\
          </h2>"
     );
 }
@@ -1536,7 +1536,7 @@ fn render_impl(
                     render_rightside(w, cx, item, containing_item, render_mode);
                     if trait_.is_some() {
                         // Anchors are only used on trait impls.
-                        write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
+                        write!(w, "<a href=\"#{}\" class=\"anchor\">§</a>", id);
                     }
                     w.write_str("<h4 class=\"code-header\">");
                     render_assoc_item(
@@ -1562,7 +1562,7 @@ fn render_impl(
                 render_rightside(w, cx, item, containing_item, render_mode);
                 if trait_.is_some() {
                     // Anchors are only used on trait impls.
-                    write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
+                    write!(w, "<a href=\"#{}\" class=\"anchor\">§</a>", id);
                 }
                 w.write_str("<h4 class=\"code-header\">");
                 assoc_const(
@@ -1587,7 +1587,7 @@ fn render_impl(
                 write!(w, "<section id=\"{}\" class=\"{}{}\">", id, item_type, in_trait_class);
                 if trait_.is_some() {
                     // Anchors are only used on trait impls.
-                    write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
+                    write!(w, "<a href=\"#{}\" class=\"anchor\">§</a>", id);
                 }
                 w.write_str("<h4 class=\"code-header\">");
                 assoc_type(
@@ -1613,7 +1613,7 @@ fn render_impl(
                 );
                 if trait_.is_some() {
                     // Anchors are only used on trait impls.
-                    write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
+                    write!(w, "<a href=\"#{}\" class=\"anchor\">§</a>", id);
                 }
                 w.write_str("<h4 class=\"code-header\">");
                 assoc_type(
@@ -1846,7 +1846,7 @@ pub(crate) fn render_impl_summary(
     };
     write!(w, "<section id=\"{}\" class=\"impl has-srclink\"{}>", id, aliases);
     render_rightside(w, cx, &i.impl_item, containing_item, RenderMode::Normal);
-    write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
+    write!(w, "<a href=\"#{}\" class=\"anchor\">§</a>", id);
     write!(w, "<h3 class=\"code-header\">");
 
     if let Some(use_absolute) = use_absolute {
@@ -2280,12 +2280,12 @@ fn sidebar_struct(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, s: &clea
     let fields = get_struct_fields_name(&s.fields);
 
     if !fields.is_empty() {
-        match s.struct_type {
-            CtorKind::Fictive => {
+        match s.ctor_kind {
+            None => {
                 print_sidebar_block(&mut sidebar, "fields", "Fields", fields.iter());
             }
-            CtorKind::Fn => print_sidebar_title(&mut sidebar, "fields", "Tuple Fields"),
-            CtorKind::Const => {}
+            Some(CtorKind::Fn) => print_sidebar_title(&mut sidebar, "fields", "Tuple Fields"),
+            Some(CtorKind::Const) => {}
         }
     }
 
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index c95f117a205..acbe3f22889 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -10,7 +10,7 @@ use rustc_middle::ty::layout::LayoutError;
 use rustc_middle::ty::{self, Adt, TyCtxt};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_target::abi::{Layout, Primitive, TagEncoding, Variants};
+use rustc_target::abi::{LayoutS, Primitive, TagEncoding, VariantIdx, Variants};
 use std::cmp::Ordering;
 use std::fmt;
 use std::rc::Rc;
@@ -717,7 +717,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
         write!(
             w,
             "<h2 id=\"{0}\" class=\"small-section-header\">\
-                {1}<a href=\"#{0}\" class=\"anchor\"></a>\
+                {1}<a href=\"#{0}\" class=\"anchor\">§</a>\
              </h2>{2}",
             id, title, extra_content
         )
@@ -1147,7 +1147,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
         write!(
             w,
             "<h2 id=\"fields\" class=\"fields small-section-header\">\
-                Fields<a href=\"#fields\" class=\"anchor\"></a>\
+                Fields<a href=\"#fields\" class=\"anchor\">§</a>\
             </h2>"
         );
         for (field, ty) in fields {
@@ -1156,7 +1156,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
             write!(
                 w,
                 "<span id=\"{id}\" class=\"{shortty} small-section-header\">\
-                     <a href=\"#{id}\" class=\"anchor field\"></a>\
+                     <a href=\"#{id}\" class=\"anchor field\">§</a>\
                      <code>{name}: {ty}</code>\
                  </span>",
                 id = id,
@@ -1232,7 +1232,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
                                     w,
                                     v,
                                     None,
-                                    s.struct_type,
+                                    s.ctor_kind,
                                     &s.fields,
                                     "    ",
                                     false,
@@ -1262,7 +1262,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
         write!(
             w,
             "<h2 id=\"variants\" class=\"variants small-section-header\">\
-                Variants{}<a href=\"#variants\" class=\"anchor\"></a>\
+                Variants{}<a href=\"#variants\" class=\"anchor\">§</a>\
             </h2>",
             document_non_exhaustive_header(it)
         );
@@ -1273,7 +1273,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
             write!(
                 w,
                 "<section id=\"{id}\" class=\"variant\">\
-                    <a href=\"#{id}\" class=\"anchor\"></a>",
+                    <a href=\"#{id}\" class=\"anchor\">§</a>",
                 id = id,
             );
             render_stability_since_raw_with_extra(
@@ -1325,7 +1325,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
                                 w,
                                 "<div class=\"sub-variant-field\">\
                                  <span id=\"{id}\" class=\"small-section-header\">\
-                                     <a href=\"#{id}\" class=\"anchor field\"></a>\
+                                     <a href=\"#{id}\" class=\"anchor field\">§</a>\
                                      <code>{f}:&nbsp;{t}</code>\
                                  </span>",
                                 id = id,
@@ -1458,7 +1458,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
     wrap_into_item_decl(w, |w| {
         wrap_item(w, "struct", |w| {
             render_attributes_in_code(w, it);
-            render_struct(w, it, Some(&s.generics), s.struct_type, &s.fields, "", true, cx);
+            render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx);
         });
     });
 
@@ -1472,14 +1472,14 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
             _ => None,
         })
         .peekable();
-    if let CtorKind::Fictive | CtorKind::Fn = s.struct_type {
+    if let None | Some(CtorKind::Fn) = s.ctor_kind {
         if fields.peek().is_some() {
             write!(
                 w,
                 "<h2 id=\"fields\" class=\"fields small-section-header\">\
-                     {}{}<a href=\"#fields\" class=\"anchor\"></a>\
+                     {}{}<a href=\"#fields\" class=\"anchor\">§</a>\
                  </h2>",
-                if let CtorKind::Fictive = s.struct_type { "Fields" } else { "Tuple Fields" },
+                if s.ctor_kind.is_none() { "Fields" } else { "Tuple Fields" },
                 document_non_exhaustive_header(it)
             );
             document_non_exhaustive(w, it);
@@ -1490,7 +1490,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
                 write!(
                     w,
                     "<span id=\"{id}\" class=\"{item_type} small-section-header\">\
-                         <a href=\"#{id}\" class=\"anchor field\"></a>\
+                         <a href=\"#{id}\" class=\"anchor field\">§</a>\
                          <code>{name}: {ty}</code>\
                      </span>",
                     item_type = ItemType::StructField,
@@ -1739,7 +1739,7 @@ fn render_struct(
     w: &mut Buffer,
     it: &clean::Item,
     g: Option<&clean::Generics>,
-    ty: CtorKind,
+    ty: Option<CtorKind>,
     fields: &[clean::Item],
     tab: &str,
     structhead: bool,
@@ -1757,7 +1757,7 @@ fn render_struct(
         write!(w, "{}", g.print(cx))
     }
     match ty {
-        CtorKind::Fictive => {
+        None => {
             let where_diplayed = g.map(|g| print_where_clause_and_check(w, g, cx)).unwrap_or(false);
 
             // If there wasn't a `where` clause, we add a whitespace.
@@ -1799,7 +1799,7 @@ fn render_struct(
             }
             w.write_str("}");
         }
-        CtorKind::Fn => {
+        Some(CtorKind::Fn) => {
             w.write_str("(");
             for (i, field) in fields.iter().enumerate() {
                 if i > 0 {
@@ -1827,7 +1827,7 @@ fn render_struct(
                 w.write_str(";");
             }
         }
-        CtorKind::Const => {
+        Some(CtorKind::Const) => {
             // Needed for PhantomData.
             if let Some(g) = g {
                 write!(w, "{}", print_where_clause(g, cx, 0, Ending::NoNewline));
@@ -1892,11 +1892,11 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) {
 }
 
 fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
-    fn write_size_of_layout(w: &mut Buffer, layout: Layout<'_>, tag_size: u64) {
-        if layout.abi().is_unsized() {
+    fn write_size_of_layout(w: &mut Buffer, layout: &LayoutS<VariantIdx>, tag_size: u64) {
+        if layout.abi.is_unsized() {
             write!(w, "(unsized)");
         } else {
-            let bytes = layout.size().bytes() - tag_size;
+            let bytes = layout.size.bytes() - tag_size;
             write!(w, "{size} byte{pl}", size = bytes, pl = if bytes == 1 { "" } else { "s" },);
         }
     }
@@ -1908,7 +1908,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
     writeln!(
         w,
         "<h2 id=\"layout\" class=\"small-section-header\"> \
-        Layout<a href=\"#layout\" class=\"anchor\"></a></h2>"
+        Layout<a href=\"#layout\" class=\"anchor\">§</a></h2>"
     );
     writeln!(w, "<div class=\"docblock\">");
 
@@ -1927,7 +1927,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
                  chapter for details on type layout guarantees.</p></div>"
             );
             w.write_str("<p><strong>Size:</strong> ");
-            write_size_of_layout(w, ty_layout.layout, 0);
+            write_size_of_layout(w, &ty_layout.layout.0, 0);
             writeln!(w, "</p>");
             if let Variants::Multiple { variants, tag, tag_encoding, .. } =
                 &ty_layout.layout.variants()
@@ -1953,7 +1953,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
                     for (index, layout) in variants.iter_enumerated() {
                         let name = adt.variant(index).name;
                         write!(w, "<li><code>{name}</code>: ", name = name);
-                        write_size_of_layout(w, *layout, tag_size);
+                        write_size_of_layout(w, layout, tag_size);
                         writeln!(w, "</li>");
                     }
                     w.write_str("</ul>");
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 2335f3ff1ce..c1f7a833834 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -701,6 +701,8 @@ a {
 }
 
 .small-section-header {
+	/* fields use <span> tags, but should get their own lines */
+	display: block;
 	position: relative;
 }
 
@@ -728,9 +730,6 @@ a {
 h2.small-section-header > .anchor {
 	padding-right: 6px;
 }
-.anchor::before {
-	content: '§';
-}
 
 .main-heading a:hover,
 .example-wrap > pre.rust a:hover,
@@ -785,8 +784,7 @@ table,
 	margin-top: 0;
 	white-space: nowrap;
 	/* flex layout allows shrinking the <select> appropriately if it becomes too large */
-	display: inline-flex;
-	max-width: 100%;
+	display: flex;
 	/* make things look like in a line, despite the fact that we're using a layout
 	with boxes (i.e. from the flex layout) */
 	align-items: baseline;
@@ -932,7 +930,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	right: var(--popover-arrow-offset);
 	border: solid var(--border-color);
 	border-width: 1px 1px 0 0;
-	display: inline-block;
 	padding: 4px;
 	transform: rotate(-45deg);
 	top: -5px;
@@ -1200,7 +1197,6 @@ pre.rust .doccomment {
 }
 
 a.test-arrow {
-	display: inline-block;
 	visibility: hidden;
 	position: absolute;
 	padding: 5px 10px 5px 10px;
@@ -1347,6 +1343,13 @@ a.test-arrow:hover {
 	border-bottom: 1px solid var(--border-color);
 	margin-bottom: 6px;
 }
+#source-sidebar div.files > a:hover, details.dir-entry summary:hover,
+#source-sidebar div.files > a:focus, details.dir-entry summary:focus {
+	background-color: var(--source-sidebar-background-hover);
+}
+#source-sidebar div.files > a.selected {
+	background-color: var(--source-sidebar-background-selected);
+}
 #sidebar-toggle > button {
 	font-size: inherit;
 	font-weight: bold;
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index eb66377670c..de7db7d438c 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -84,6 +84,8 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--crate-search-div-hover-filter: invert(98%) sepia(12%) saturate(81%) hue-rotate(343deg)
 		brightness(113%) contrast(76%);
 	--crate-search-hover-border: #e0e0e0;
+	--source-sidebar-background-selected: #14191f;
+	--source-sidebar-background-hover: #14191f;
 }
 
 h1, h2, h3, h4 {
@@ -208,12 +210,8 @@ pre.rust .kw-2, pre.rust .prelude-ty {}
 	color: #fff;
 }
 #source-sidebar div.files > a:hover, details.dir-entry summary:hover,
-#source-sidebar div.files > a:focus, details.dir-entry summary:focus {
-	background-color: #14191f;
-	color: #ffb44c;
-}
+#source-sidebar div.files > a:focus, details.dir-entry summary:focus,
 #source-sidebar div.files > a.selected {
-	background-color: #14191f;
 	color: #ffb44c;
 }
 
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 44598a6b778..d8929f32338 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -79,6 +79,8 @@
 	--crate-search-div-hover-filter: invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg)
 		brightness(100%) contrast(91%);
 	--crate-search-hover-border: #2196f3;
+	--source-sidebar-background-selected: #333;
+	--source-sidebar-background-hover: #444;
 }
 
 .content .item-info::before { color: #ccc; }
@@ -105,14 +107,6 @@ details.rustdoc-toggle > summary::before {
 	color: #888;
 }
 
-#source-sidebar div.files > a:hover, details.dir-entry summary:hover,
-#source-sidebar div.files > a:focus, details.dir-entry summary:focus {
-	background-color: #444;
-}
-#source-sidebar div.files > a.selected {
-	background-color: #333;
-}
-
 .scraped-example-list .scrape-help {
 	border-color: #aaa;
 	color: #eee;
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index f0db14fd59f..ff6c6863533 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -76,6 +76,8 @@
 	--crate-search-div-hover-filter: invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg)
 		brightness(96%) contrast(93%);
 	--crate-search-hover-border: #717171;
+	--source-sidebar-background-selected: #fff;
+	--source-sidebar-background-hover: #e0e0e0;
 }
 
 .content .item-info::before { color: #ccc; }
@@ -98,13 +100,6 @@ body.source .example-wrap pre.rust a {
 	color: #888;
 }
 
-#source-sidebar div.files > a:hover, details.dir-entry summary:hover,
-#source-sidebar div.files > a:focus, details.dir-entry summary:focus {
-	background-color: #E0E0E0;
-}
-#source-sidebar div.files > a.selected {
-	background-color: #fff;
-}
 .scraped-example-list .scrape-help {
 	border-color: #555;
 	color: #333;
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index df13e597f1f..aa3bf827db4 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -115,6 +115,7 @@
                     <input {# -#}
                         class="search-input" {# -#}
                         name="search" {# -#}
+                        aria-label="Run search in the documentation" {# -#}
                         autocomplete="off" {# -#}
                         spellcheck="false" {# -#}
                         placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {# -#}
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 6995778a93d..d7184053c87 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -315,15 +315,15 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
 impl FromWithTcx<clean::Struct> for Struct {
     fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self {
         let fields_stripped = struct_.has_stripped_entries();
-        let clean::Struct { struct_type, generics, fields } = struct_;
+        let clean::Struct { ctor_kind, generics, fields } = struct_;
 
-        let kind = match struct_type {
-            CtorKind::Fn => StructKind::Tuple(ids_keeping_stripped(fields, tcx)),
-            CtorKind::Const => {
+        let kind = match ctor_kind {
+            Some(CtorKind::Fn) => StructKind::Tuple(ids_keeping_stripped(fields, tcx)),
+            Some(CtorKind::Const) => {
                 assert!(fields.is_empty());
                 StructKind::Unit
             }
-            CtorKind::Fictive => StructKind::Plain { fields: ids(fields, tcx), fields_stripped },
+            None => StructKind::Plain { fields: ids(fields, tcx), fields_stripped },
         };
 
         Struct {
diff --git a/src/test/codegen/async-fn-debug-awaitee-field.rs b/src/test/codegen/async-fn-debug-awaitee-field.rs
index 909cd0062a6..bc268615814 100644
--- a/src/test/codegen/async-fn-debug-awaitee-field.rs
+++ b/src/test/codegen/async-fn-debug-awaitee-field.rs
@@ -11,12 +11,14 @@ async fn async_fn_test() {
     foo().await;
 }
 
-// NONMSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}",
+// NONMSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[GEN_SCOPE:![0-9]*]],
 // MSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_awaitee_field::async_fn_test::async_fn_env$0>",
+// NONMSVC: [[GEN_SCOPE:!.*]] = !DINamespace(name: "async_fn_test",
 // CHECK: [[SUSPEND_STRUCT:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend0", scope: [[GEN]],
 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__awaitee", scope: [[SUSPEND_STRUCT]], {{.*}}, baseType: [[AWAITEE_TYPE:![0-9]*]],
-// NONMSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture<async_fn_debug_awaitee_field::foo::{async_fn_env#0}>",
-// MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture<enum2$<async_fn_debug_awaitee_field::foo::async_fn_env$0> >",
+// NONMSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[AWAITEE_SCOPE:![0-9]*]],
+// MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_awaitee_field::foo::async_fn_env$0>",
+// NONMSVC: [[AWAITEE_SCOPE]] = !DINamespace(name: "foo",
 
 fn main() {
     let _fn = async_fn_test();
diff --git a/src/test/codegen/issue-37945.rs b/src/test/codegen/issue-37945.rs
index 12fa1e9e56b..fe54375bbf6 100644
--- a/src/test/codegen/issue-37945.rs
+++ b/src/test/codegen/issue-37945.rs
@@ -15,7 +15,7 @@ use std::slice::Iter;
 pub fn is_empty_1(xs: Iter<f32>) -> bool {
 // CHECK-LABEL: @is_empty_1(
 // CHECK-NEXT:  start:
-// CHECK-NEXT:    [[A:%.*]] = icmp ne {{i32\*|ptr}} %xs.1, null
+// CHECK-NEXT:    [[A:%.*]] = icmp ne {{i32\*|ptr}} {{%xs.0|%xs.1}}, null
 // CHECK-NEXT:    tail call void @llvm.assume(i1 [[A]])
 // The order between %xs.0 and %xs.1 on the next line doesn't matter
 // and different LLVM versions produce different order.
@@ -28,7 +28,7 @@ pub fn is_empty_1(xs: Iter<f32>) -> bool {
 pub fn is_empty_2(xs: Iter<f32>) -> bool {
 // CHECK-LABEL: @is_empty_2
 // CHECK-NEXT:  start:
-// CHECK-NEXT:    [[C:%.*]] = icmp ne {{i32\*|ptr}} %xs.1, null
+// CHECK-NEXT:    [[C:%.*]] = icmp ne {{i32\*|ptr}} {{%xs.0|%xs.1}}, null
 // CHECK-NEXT:    tail call void @llvm.assume(i1 [[C]])
 // The order between %xs.0 and %xs.1 on the next line doesn't matter
 // and different LLVM versions produce different order.
diff --git a/src/test/codegen/mem-replace-direct-memcpy.rs b/src/test/codegen/mem-replace-direct-memcpy.rs
index 4318e926e47..e8bbf0e1bbd 100644
--- a/src/test/codegen/mem-replace-direct-memcpy.rs
+++ b/src/test/codegen/mem-replace-direct-memcpy.rs
@@ -18,7 +18,7 @@ pub fn replace_byte(dst: &mut u8, src: u8) -> u8 {
 // CHECK-NOT: call void @llvm.memcpy
 // CHECK: ; core::mem::replace
 // CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %dest, i{{.*}} 1, i1 false)
+// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{.*}} 1, i1 false)
 // CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %dest, {{i8\*|ptr}} align 1 %src{{.*}}, i{{.*}} 1, i1 false)
+// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{.*}} 1, i1 false)
 // CHECK-NOT: call void @llvm.memcpy
diff --git a/src/test/codegen/slice-iter-len-eq-zero.rs b/src/test/codegen/slice-iter-len-eq-zero.rs
index 1124028253d..894b0ec3de4 100644
--- a/src/test/codegen/slice-iter-len-eq-zero.rs
+++ b/src/test/codegen/slice-iter-len-eq-zero.rs
@@ -9,7 +9,7 @@ type Demo = [u8; 3];
 #[no_mangle]
 pub fn slice_iter_len_eq_zero(y: std::slice::Iter<'_, Demo>) -> bool {
     // CHECK-NOT: sub
-    // CHECK: %2 = icmp eq {{i8\*|ptr}} %1, %0
+    // CHECK: %2 = icmp eq {{i8\*|ptr}} {{%1|%0}}, {{%1|%0}}
     // CHECK: ret i1 %2
     y.len() == 0
 }
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.async2.txt b/src/test/run-make/coverage-reports/expected_show_coverage.async2.txt
index dc06a485a8f..500dde1f269 100644
--- a/src/test/run-make/coverage-reports/expected_show_coverage.async2.txt
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.async2.txt
@@ -72,7 +72,7 @@
    67|       |        }
    68|      2|    }
   ------------------
-  | async2::executor::block_on::<core::future::from_generator::GenFuture<async2::async_func::{closure#0}>>:
+  | async2::executor::block_on::<async2::async_func::{closure#0}>:
   |   51|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
   |   52|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
   |   53|      1|        use std::hint::unreachable_unchecked;
@@ -92,7 +92,7 @@
   |   67|       |        }
   |   68|      1|    }
   ------------------
-  | async2::executor::block_on::<core::future::from_generator::GenFuture<async2::async_func_just_println::{closure#0}>>:
+  | async2::executor::block_on::<async2::async_func_just_println::{closure#0}>:
   |   51|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
   |   52|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
   |   53|      1|        use std::hint::unreachable_unchecked;
diff --git a/src/test/run-make/rustdoc-verify-output-files/Makefile b/src/test/run-make/rustdoc-verify-output-files/Makefile
new file mode 100644
index 00000000000..bfabbbc6586
--- /dev/null
+++ b/src/test/run-make/rustdoc-verify-output-files/Makefile
@@ -0,0 +1,36 @@
+include ../../run-make-fulldeps/tools.mk
+
+OUTPUT_DIR := "$(TMPDIR)/rustdoc"
+TMP_OUTPUT_DIR := "$(TMPDIR)/tmp-rustdoc"
+
+all:
+	# Generate html docs
+	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR)
+
+	# Copy first output for to check if it's exactly same after second compilation
+	cp -R $(OUTPUT_DIR) $(TMP_OUTPUT_DIR)
+
+	# Generate html docs once again on same output
+	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR)
+
+	# Check if everything exactly same
+	$(DIFF) -r -q $(OUTPUT_DIR) $(TMP_OUTPUT_DIR)
+
+	# Generate json doc on the same output
+	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) -Z unstable-options --output-format json
+
+	# Check if expected json file is generated
+	[ -e $(OUTPUT_DIR)/foobar.json ]
+
+	# TODO
+	# We should re-generate json doc once again and compare the diff with previously
+	# generated one. Because layout of json docs changes in each compilation, we can't
+	# do that currently.
+	#
+	# See https://github.com/rust-lang/rust/issues/103785#issuecomment-1307425590 for details.
+
+	# remove generated json doc
+	rm $(OUTPUT_DIR)/foobar.json
+
+	# Check if json doc compilation broke any of the html files generated previously
+	$(DIFF) -r -q $(OUTPUT_DIR) $(TMP_OUTPUT_DIR)
diff --git a/src/test/run-make/rustdoc-verify-output-files/src/lib.rs b/src/test/run-make/rustdoc-verify-output-files/src/lib.rs
new file mode 100644
index 00000000000..5df7576133a
--- /dev/null
+++ b/src/test/run-make/rustdoc-verify-output-files/src/lib.rs
@@ -0,0 +1 @@
+// nothing to see here
diff --git a/src/test/rustdoc-gui/search-result-display.goml b/src/test/rustdoc-gui/search-result-display.goml
index fa349c872ae..13a5e4c717b 100644
--- a/src/test/rustdoc-gui/search-result-display.goml
+++ b/src/test/rustdoc-gui/search-result-display.goml
@@ -22,7 +22,8 @@ size: (900, 900)
 
 // First we check the current width, height and position.
 assert-css: ("#crate-search", {"width": "223px"})
-assert-css: (".search-results-title", {"height": "44px", "width": "336px"})
+assert-css: (".search-results-title", {"height": "44px", "width": "640px"})
+assert-css: ("#search", {"width": "640px"})
 
 // Then we update the text of one of the `<option>`.
 text: (
diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml
index abf8af77715..40ae4af81be 100644
--- a/src/test/rustdoc-gui/sidebar-source-code-display.goml
+++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml
@@ -43,16 +43,24 @@ define-function: (
             "#source-sidebar details[open] > .files a.selected",
             {"color": |color_hover|, "background-color": |background|},
         )),
+
         // Without hover or focus.
         ("assert-css", ("#sidebar-toggle > button", {"background-color": |background_toggle|})),
         // With focus.
         ("focus", "#sidebar-toggle > button"),
-        ("assert-css", ("#sidebar-toggle > button", {"background-color": |background_toggle_hover|})),
+        ("assert-css", (
+            "#sidebar-toggle > button:focus",
+            {"background-color": |background_toggle_hover|},
+        )),
         ("focus", ".search-input"),
         // With hover.
         ("move-cursor-to", "#sidebar-toggle > button"),
-        ("assert-css", ("#sidebar-toggle > button", {"background-color": |background_toggle_hover|})),
-        // Without hover.
+        ("assert-css", (
+            "#sidebar-toggle > button:hover",
+            {"background-color": |background_toggle_hover|},
+        )),
+
+        // Without hover or focus.
         ("assert-css", (
             "#source-sidebar details[open] > .files a:not(.selected)",
             {"color": |color|, "background-color": |background_toggle|},
@@ -60,17 +68,37 @@ define-function: (
         // With focus.
         ("focus", "#source-sidebar details[open] > .files a:not(.selected)"),
         ("wait-for-css", (
-            "#source-sidebar details[open] > .files a:not(.selected)",
+            "#source-sidebar details[open] > .files a:not(.selected):focus",
             {"color": |color_hover|, "background-color": |background_hover|},
         )),
         ("focus", ".search-input"),
         // With hover.
         ("move-cursor-to", "#source-sidebar details[open] > .files a:not(.selected)"),
         ("assert-css", (
-            "#source-sidebar details[open] > .files a:not(.selected)",
+            "#source-sidebar details[open] > .files a:not(.selected):hover",
             {"color": |color_hover|, "background-color": |background_hover|},
         )),
-        // Without hover.
+
+        // Without hover or focus.
+        ("assert-css", (
+            "#source-sidebar .dir-entry summary",
+            {"color": |color|, "background-color": |background_toggle|},
+        )),
+        // With focus.
+        ("focus", "#source-sidebar .dir-entry summary"),
+        ("wait-for-css", (
+            "#source-sidebar .dir-entry summary:focus",
+            {"color": |color_hover|, "background-color": |background_hover|},
+        )),
+        ("focus", ".search-input"),
+        // With hover.
+        ("move-cursor-to", "#source-sidebar .dir-entry summary"),
+        ("assert-css", (
+            "#source-sidebar .dir-entry summary:hover",
+            {"color": |color_hover|, "background-color": |background_hover|},
+        )),
+
+        // Without hover or focus.
         ("assert-css", (
             "#source-sidebar details[open] > .folders > details > summary",
             {"color": |color|, "background-color": |background_toggle|},
@@ -78,14 +106,14 @@ define-function: (
         // With focus.
         ("focus", "#source-sidebar details[open] > .folders > details > summary"),
         ("wait-for-css", (
-            "#source-sidebar details[open] > .folders > details > summary",
+            "#source-sidebar details[open] > .folders > details > summary:focus",
             {"color": |color_hover|, "background-color": |background_hover|},
         )),
         ("focus", ".search-input"),
         // With hover.
         ("move-cursor-to", "#source-sidebar details[open] > .folders > details > summary"),
         ("assert-css", (
-            "#source-sidebar details[open] > .folders > details > summary",
+            "#source-sidebar details[open] > .folders > details > summary:hover",
             {"color": |color_hover|, "background-color": |background_hover|},
         )),
     ],
diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs
index 8eea5ad01c0..dea154c9319 100644
--- a/src/test/rustdoc-gui/src/test_docs/lib.rs
+++ b/src/test/rustdoc-gui/src/test_docs/lib.rs
@@ -408,6 +408,11 @@ pub struct WithGenerics<T: TraitWithNoDocblocks, S = String, E = WhoLetTheDogOut
     p: P,
 }
 
+pub struct StructWithPublicUndocumentedFields {
+    pub first: u32,
+    pub second: u32,
+}
+
 pub const CONST: u8 = 0;
 
 pub trait TraitWithoutGenerics {
diff --git a/src/test/rustdoc-gui/struct-fields.goml b/src/test/rustdoc-gui/struct-fields.goml
new file mode 100644
index 00000000000..3ec60b58cfd
--- /dev/null
+++ b/src/test/rustdoc-gui/struct-fields.goml
@@ -0,0 +1,5 @@
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.StructWithPublicUndocumentedFields.html"
+
+// Both fields must be on their own line. In other words, they have display: block.
+store-property: (first_top, "//*[@id='structfield.first']", "offsetTop")
+assert-property-false: ("//*[@id='structfield.second']", { "offsetTop": |first_top| })
diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
index 2a08d5d6ce5..b8ca64fae83 100644
--- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
+++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
@@ -1,8 +1,7 @@
 error[E0267]: `break` inside of an `async` block
   --> $DIR/async-block-control-flow-static-semantics.rs:32:9
    |
-LL |       async {
-   |  ___________-
+LL | /     async {
 LL | |         break 0u8;
    | |         ^^^^^^^^^ cannot `break` inside of an `async` block
 LL | |     };
@@ -11,8 +10,7 @@ LL | |     };
 error[E0267]: `break` inside of an `async` block
   --> $DIR/async-block-control-flow-static-semantics.rs:39:13
    |
-LL |           async {
-   |  _______________-
+LL | /         async {
 LL | |             break 0u8;
    | |             ^^^^^^^^^ cannot `break` inside of an `async` block
 LL | |         };
diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
index f21c8115124..190c59e32eb 100644
--- a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
+++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
@@ -1,11 +1,11 @@
 error[E0373]: async block may outlive the current function, but it borrows `x`, which is owned by the current function
-  --> $DIR/async-borrowck-escaping-block-error.rs:6:20
+  --> $DIR/async-borrowck-escaping-block-error.rs:6:14
    |
 LL |     Box::new(async { x } )
-   |                    ^^-^^
-   |                    | |
-   |                    | `x` is borrowed here
-   |                    may outlive borrowed value `x`
+   |              ^^^^^^^^-^^
+   |              |       |
+   |              |       `x` is borrowed here
+   |              may outlive borrowed value `x`
    |
 note: async block is returned here
   --> $DIR/async-borrowck-escaping-block-error.rs:6:5
@@ -18,13 +18,13 @@ LL |     Box::new(async move { x } )
    |                    ++++
 
 error[E0373]: async block may outlive the current function, but it borrows `x`, which is owned by the current function
-  --> $DIR/async-borrowck-escaping-block-error.rs:11:11
+  --> $DIR/async-borrowck-escaping-block-error.rs:11:5
    |
 LL |     async { *x }
-   |           ^^--^^
-   |           | |
-   |           | `x` is borrowed here
-   |           may outlive borrowed value `x`
+   |     ^^^^^^^^--^^
+   |     |       |
+   |     |       `x` is borrowed here
+   |     may outlive borrowed value `x`
    |
 note: async block is returned here
   --> $DIR/async-borrowck-escaping-block-error.rs:11:5
diff --git a/src/test/ui/async-await/drop-tracking-unresolved-typeck-results.rs b/src/test/ui/async-await/drop-tracking-unresolved-typeck-results.rs
new file mode 100644
index 00000000000..7f729429581
--- /dev/null
+++ b/src/test/ui/async-await/drop-tracking-unresolved-typeck-results.rs
@@ -0,0 +1,106 @@
+// compile-flags: -Zdrop-tracking
+// incremental
+// edition: 2021
+
+use std::future::*;
+use std::marker::PhantomData;
+use std::pin::Pin;
+use std::task::*;
+
+fn send<T: Send>(_: T) {}
+
+pub trait Stream {
+    type Item;
+
+    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>;
+}
+
+struct Empty<T>(PhantomData<fn() -> T>);
+
+impl<T> Stream for Empty<T> {
+    type Item = T;
+
+    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
+        todo!()
+    }
+}
+
+pub trait FnOnce1<A> {
+    type Output;
+    fn call_once(self, arg: A) -> Self::Output;
+}
+
+impl<T, A, R> FnOnce1<A> for T
+where
+    T: FnOnce(A) -> R,
+{
+    type Output = R;
+    fn call_once(self, arg: A) -> R {
+        self(arg)
+    }
+}
+
+pub trait FnMut1<A>: FnOnce1<A> {
+    fn call_mut(&mut self, arg: A) -> Self::Output;
+}
+
+impl<T, A, R> FnMut1<A> for T
+where
+    T: FnMut(A) -> R,
+{
+    fn call_mut(&mut self, arg: A) -> R {
+        self(arg)
+    }
+}
+
+struct Map<St, F>(St, F);
+
+impl<St, F> Stream for Map<St, F>
+where
+    St: Stream,
+    F: FnMut1<St::Item>,
+{
+    type Item = F::Output;
+
+    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
+        todo!()
+    }
+}
+
+struct FuturesOrdered<T: Future>(PhantomData<fn() -> T::Output>);
+
+pub struct Buffered<St: Stream>(St, FuturesOrdered<St::Item>, usize)
+where
+    St::Item: Future;
+
+impl<St> Stream for Buffered<St>
+where
+    St: Stream,
+    St::Item: Future,
+{
+    type Item = <St::Item as Future>::Output;
+
+    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
+        todo!()
+    }
+}
+
+struct Next<'a, T: ?Sized>(&'a T);
+
+impl<St: ?Sized + Stream + Unpin> Future for Next<'_, St> {
+    type Output = Option<St::Item>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        todo!()
+    }
+}
+
+fn main() {
+    send(async {
+        //~^ ERROR implementation of `FnOnce` is not general enough
+        //~| ERROR implementation of `FnOnce` is not general enough
+        //~| ERROR implementation of `FnOnce` is not general enough
+        //~| ERROR implementation of `FnOnce` is not general enough
+        Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await
+    });
+}
diff --git a/src/test/ui/async-await/drop-tracking-unresolved-typeck-results.stderr b/src/test/ui/async-await/drop-tracking-unresolved-typeck-results.stderr
new file mode 100644
index 00000000000..aa9a22e9e72
--- /dev/null
+++ b/src/test/ui/async-await/drop-tracking-unresolved-typeck-results.stderr
@@ -0,0 +1,62 @@
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5
+   |
+LL | /     send(async {
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |         Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await
+LL | |     });
+   | |______^ implementation of `FnOnce` is not general enough
+   |
+   = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`...
+   = note: ...but it actually implements `FnOnce<(&(),)>`
+
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5
+   |
+LL | /     send(async {
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |         Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await
+LL | |     });
+   | |______^ implementation of `FnOnce` is not general enough
+   |
+   = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`...
+   = note: ...but it actually implements `FnOnce<(&(),)>`
+
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5
+   |
+LL | /     send(async {
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |         Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await
+LL | |     });
+   | |______^ implementation of `FnOnce` is not general enough
+   |
+   = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`...
+   = note: ...but it actually implements `FnOnce<(&(),)>`
+
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5
+   |
+LL | /     send(async {
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |         Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await
+LL | |     });
+   | |______^ implementation of `FnOnce` is not general enough
+   |
+   = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`...
+   = note: ...but it actually implements `FnOnce<(&(),)>`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/async-await/generator-desc.stderr b/src/test/ui/async-await/generator-desc.stderr
index 2494c3feb2a..774c97966b1 100644
--- a/src/test/ui/async-await/generator-desc.stderr
+++ b/src/test/ui/async-await/generator-desc.stderr
@@ -1,20 +1,20 @@
 error[E0308]: mismatched types
-  --> $DIR/generator-desc.rs:10:25
+  --> $DIR/generator-desc.rs:10:19
    |
 LL |     fun(async {}, async {});
-   |               --        ^^
-   |               |         |
-   |               |         expected `async` block, found a different `async` block
-   |               |         arguments to this function are incorrect
-   |               the expected `async` block
+   |         --------  ^^^^^^^^
+   |         |         |
+   |         |         expected `async` block, found a different `async` block
+   |         |         arguments to this function are incorrect
+   |         the expected `async` block
    |
-   = note: expected `async` block `[static generator@$DIR/generator-desc.rs:10:15: 10:17]`
-              found `async` block `[static generator@$DIR/generator-desc.rs:10:25: 10:27]`
+   = note: expected `async` block `impl Future<Output = ()>` (`async` block)
+              found `async` block `impl Future<Output = ()>` (`async` block)
 note: function defined here
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |              ^^^^^^^^^^^^^^
+LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
+   |              ^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/generator-desc.rs:12:16
@@ -53,16 +53,8 @@ LL |     fun((async || {})(), (async || {})());
    |     |             the expected `async` closure body
    |     arguments to this function are incorrect
    |
-  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |                                           -------------------------------
-   |                                           |
-   |                                           the expected opaque type
-   |                                           the found opaque type
-   |
-   = note: expected opaque type `impl Future<Output = ()>` (`async` closure body)
-              found opaque type `impl Future<Output = ()>` (`async` closure body)
+   = note: expected `async` closure body `impl Future<Output = ()>` (`async` closure body)
+              found `async` closure body `impl Future<Output = ()>` (`async` closure body)
 note: function defined here
   --> $DIR/generator-desc.rs:8:4
    |
diff --git a/src/test/ui/async-await/issue-68112.drop_tracking.stderr b/src/test/ui/async-await/issue-68112.drop_tracking.stderr
index c915164cfce..f2802698fd5 100644
--- a/src/test/ui/async-await/issue-68112.drop_tracking.stderr
+++ b/src/test/ui/async-await/issue-68112.drop_tracking.stderr
@@ -59,10 +59,10 @@ LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `Ready<i32>`
 note: required because it's used within this `async` block
-  --> $DIR/issue-68112.rs:60:26
+  --> $DIR/issue-68112.rs:60:20
    |
 LL |       let send_fut = async {
-   |  __________________________^
+   |  ____________________^
 LL | |         let non_send_fut = make_non_send_future2();
 LL | |         let _ = non_send_fut.await;
 LL | |         ready(0).await;
diff --git a/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr b/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr
index 11b7d1aaaa6..38eb85b302f 100644
--- a/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr
+++ b/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr
@@ -59,10 +59,10 @@ LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `i32`, `Ready<i32>`
 note: required because it's used within this `async` block
-  --> $DIR/issue-68112.rs:60:26
+  --> $DIR/issue-68112.rs:60:20
    |
 LL |       let send_fut = async {
-   |  __________________________^
+   |  ____________________^
 LL | |         let non_send_fut = make_non_send_future2();
 LL | |         let _ = non_send_fut.await;
 LL | |         ready(0).await;
diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
index 7fb88116665..721234aa4a7 100644
--- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
+++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
@@ -20,10 +20,9 @@ LL | | }
    | |_^
    = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = ()>`, `()`
 note: required because it's used within this `async` block
-  --> $DIR/issue-70935-complex-spans.rs:16:16
+  --> $DIR/issue-70935-complex-spans.rs:16:5
    |
-LL |       async move {
-   |  ________________^
+LL | /     async move {
 LL | |         baz(|| async{
 LL | |             foo(tx.clone());
 LL | |         }).await;
diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.stderr b/src/test/ui/async-await/issues/issue-78938-async-block.stderr
index 29aa8372f87..c1a4b467f10 100644
--- a/src/test/ui/async-await/issues/issue-78938-async-block.stderr
+++ b/src/test/ui/async-await/issues/issue-78938-async-block.stderr
@@ -1,8 +1,8 @@
 error[E0373]: async block may outlive the current function, but it borrows `room_ref`, which is owned by the current function
-  --> $DIR/issue-78938-async-block.rs:8:39
+  --> $DIR/issue-78938-async-block.rs:8:33
    |
 LL |       let gameloop_handle = spawn(async {
-   |  _______________________________________^
+   |  _________________________________^
 LL | |         game_loop(Arc::clone(&room_ref))
    | |                               -------- `room_ref` is borrowed here
 LL | |     });
diff --git a/src/test/ui/async-await/try-on-option-in-async.stderr b/src/test/ui/async-await/try-on-option-in-async.stderr
index a55850d76c3..4c7b4fa41fa 100644
--- a/src/test/ui/async-await/try-on-option-in-async.stderr
+++ b/src/test/ui/async-await/try-on-option-in-async.stderr
@@ -1,8 +1,7 @@
 error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-in-async.rs:8:10
    |
-LL |       async {
-   |  ___________-
+LL | /     async {
 LL | |         let x: Option<u32> = None;
 LL | |         x?;
    | |          ^ cannot use the `?` operator in an async block that returns `{integer}`
diff --git a/src/test/ui/binding/issue-53114-borrow-checks.stderr b/src/test/ui/binding/issue-53114-borrow-checks.stderr
index 489bf70d920..0ec2ae8839e 100644
--- a/src/test/ui/binding/issue-53114-borrow-checks.stderr
+++ b/src/test/ui/binding/issue-53114-borrow-checks.stderr
@@ -17,6 +17,10 @@ LL |     match mm { (_, _y) => { } }
    |           ^^ value used here after partial move
    |
    = note: partial move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     match mm { (ref _x, _) => { } }
+   |                 +++
 
 error[E0382]: use of partially moved value: `mm`
   --> $DIR/issue-53114-borrow-checks.rs:29:11
@@ -28,6 +32,10 @@ LL |     match mm { (_, _) => { } }
    |           ^^ value used here after partial move
    |
    = note: partial move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     match mm { (_, ref _y) => { } }
+   |                    +++
 
 error[E0382]: use of moved value: `m`
   --> $DIR/issue-53114-borrow-checks.rs:36:16
@@ -48,6 +56,10 @@ LL |     if let (_, _y) = mm { }
    |                      ^^ value used here after partial move
    |
    = note: partial move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     if let (ref _x, _) = mm { }
+   |             +++
 
 error[E0382]: use of partially moved value: `mm`
   --> $DIR/issue-53114-borrow-checks.rs:43:21
@@ -59,6 +71,10 @@ LL |     if let (_, _) = mm { }
    |                     ^^ value used here after partial move
    |
    = note: partial move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     if let (_, ref _y) = mm { }
+   |                +++
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/binop/binop-move-semantics.stderr b/src/test/ui/binop/binop-move-semantics.stderr
index 695b01d5ee3..994eaf9d8c7 100644
--- a/src/test/ui/binop/binop-move-semantics.stderr
+++ b/src/test/ui/binop/binop-move-semantics.stderr
@@ -32,6 +32,10 @@ LL |     +
 LL |     x.clone();
    |     ^^^^^^^^^ value borrowed here after move
    |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     x.clone()
+   |      ++++++++
 help: consider further restricting this bound
    |
 LL | fn move_then_borrow<T: Add<Output=()> + Clone + Copy>(x: T) {
diff --git a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
index 1fd1eb12851..50eee1049db 100644
--- a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
+++ b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
@@ -27,6 +27,11 @@ LL |         a @ [.., _] => (),
 ...
 LL |     &x;
    |     ^^ value borrowed here after move
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref a @ [.., _] => (),
+   |         +++
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
   --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:28:5
@@ -71,13 +76,15 @@ LL | fn bindings_after_at_or_patterns_move(x: Option<Test>) {
    |                                       - move occurs because `x` has type `Option<Test>`, which does not implement the `Copy` trait
 LL |     match x {
 LL |         foo @ Some(Test::Foo | Test::Bar) => (),
-   |         ---
-   |         |
-   |         value moved here
-   |         value moved here
+   |         --- value moved here
 ...
 LL |     &x;
    |     ^^ value borrowed here after move
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref foo @ Some(Test::Foo | Test::Bar) => (),
+   |         +++
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
   --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:86:5
@@ -122,13 +129,15 @@ LL | fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option<Test>; 4])
    |                                                       - move occurs because `x` has type `[Option<Test>; 4]`, which does not implement the `Copy` trait
 LL |     match x {
 LL |         a @ [.., Some(Test::Foo | Test::Bar)] => (),
-   |         -
-   |         |
-   |         value moved here
-   |         value moved here
+   |         - value moved here
 ...
 LL |     &x;
    |     ^^ value borrowed here after move
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref a @ [.., Some(Test::Foo | Test::Bar)] => (),
+   |         +++
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
   --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:144:5
diff --git a/src/test/ui/borrowck/borrowck-consume-unsize-vec.stderr b/src/test/ui/borrowck/borrowck-consume-unsize-vec.stderr
index 17b93106615..d2e9497d079 100644
--- a/src/test/ui/borrowck/borrowck-consume-unsize-vec.stderr
+++ b/src/test/ui/borrowck/borrowck-consume-unsize-vec.stderr
@@ -7,6 +7,18 @@ LL |     consume(b);
    |             - value moved here
 LL |     consume(b);
    |             ^ value used here after move
+   |
+note: consider changing this parameter type in function `consume` to borrow instead if owning the value isn't necessary
+  --> $DIR/borrowck-consume-unsize-vec.rs:3:15
+   |
+LL | fn consume(_: Box<[i32]>) {
+   |    -------    ^^^^^^^^^^ this parameter takes ownership of the value
+   |    |
+   |    in this function
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     consume(b.clone());
+   |              ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-consume-upcast-box.stderr b/src/test/ui/borrowck/borrowck-consume-upcast-box.stderr
index 4e20bbf1757..ed7e883ca63 100644
--- a/src/test/ui/borrowck/borrowck-consume-upcast-box.stderr
+++ b/src/test/ui/borrowck/borrowck-consume-upcast-box.stderr
@@ -7,6 +7,14 @@ LL |     consume(b);
    |             - value moved here
 LL |     consume(b);
    |             ^ value used here after move
+   |
+note: consider changing this parameter type in function `consume` to borrow instead if owning the value isn't necessary
+  --> $DIR/borrowck-consume-upcast-box.rs:5:15
+   |
+LL | fn consume(_: Box<dyn Foo>) {
+   |    -------    ^^^^^^^^^^^^ this parameter takes ownership of the value
+   |    |
+   |    in this function
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-drop-from-guard.stderr b/src/test/ui/borrowck/borrowck-drop-from-guard.stderr
index cd0d2fee942..eaf4bb38bc5 100644
--- a/src/test/ui/borrowck/borrowck-drop-from-guard.stderr
+++ b/src/test/ui/borrowck/borrowck-drop-from-guard.stderr
@@ -9,6 +9,11 @@ LL |         Some(_) if { drop(my_str); false } => {}
 LL |         Some(_) => {}
 LL |         None => { foo(my_str); }
    |                       ^^^^^^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         Some(_) if { drop(my_str.clone()); false } => {}
+   |                                 ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr
index 0dd720ff6ce..e1b99162088 100644
--- a/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr
+++ b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr
@@ -7,6 +7,11 @@ LL |     let _y = {x} + x.clone(); // the `{x}` forces a move to occur
    |               -    ^^^^^^^^^ value borrowed here after move
    |               |
    |               value moved here
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _y = {x.clone()} + x.clone(); // the `{x}` forces a move to occur
+   |                ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr
index 346b82a2666..67b00c1dd90 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr
@@ -8,6 +8,10 @@ LL |         [.., _y] => {}
    |              ^^ value used here after move
    |
    = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, ref _x] => {}
+   |                +++
 
 error[E0382]: use of partially moved value: `a[..]`
   --> $DIR/borrowck-move-out-from-array-match.rs:23:14
@@ -19,6 +23,10 @@ LL |         [.., _y] => {}
    |              ^^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, (ref _x, _)] => {}
+   |                 +++
 
 error[E0382]: use of moved value: `a[..].0`
   --> $DIR/borrowck-move-out-from-array-match.rs:33:15
@@ -30,6 +38,10 @@ LL |         [.., (_y, _)] => {}
    |               ^^ value used here after move
    |
    = note: move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, (ref _x, _)] => {}
+   |                 +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-match.rs:44:11
@@ -41,6 +53,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [ref _x, _, _] => {}
+   |          +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-match.rs:55:11
@@ -52,6 +68,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [.., ref _x] => {}
+   |              +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-match.rs:66:11
@@ -63,6 +83,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [(ref _x, _), _, _] => {}
+   |           +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-match.rs:77:11
@@ -74,6 +98,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [.., (ref _x, _)] => {}
+   |               +++
 
 error[E0382]: use of moved value: `a[..].0`
   --> $DIR/borrowck-move-out-from-array-match.rs:89:11
@@ -85,6 +113,10 @@ LL |         [(_x, _), _, _] => {}
    |           ^^ value used here after move
    |
    = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [ref _y @ .., _, _] => {}
+   |          +++
 
 error[E0382]: use of moved value: `a[..].0`
   --> $DIR/borrowck-move-out-from-array-match.rs:99:15
@@ -96,6 +128,10 @@ LL |         [.., (_x, _)] => {}
    |               ^^ value used here after move
    |
    = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, ref _y @ ..] => {}
+   |                +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-match.rs:110:11
@@ -107,6 +143,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [ref x @ .., _] => {}
+   |          +++
 
 error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr
index 6c6a25c251e..47429ea3eeb 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr
@@ -8,6 +8,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, ref _x] => {}
+   |                +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:28:11
@@ -19,6 +23,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, (ref _x, _)] => {}
+   |                 +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:41:11
@@ -30,6 +38,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [ref _x, _, _] => {}
+   |          +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:52:11
@@ -41,6 +53,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [.., ref _x] => {}
+   |              +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:63:11
@@ -52,6 +68,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [(ref _x, _), _, _] => {}
+   |           +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:74:11
@@ -63,6 +83,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [.., (ref _x, _)] => {}
+   |               +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:85:11
@@ -74,6 +98,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, ref _y @ ..] => {}
+   |             +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:96:11
@@ -85,6 +113,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [ref _y @ .., _] => {}
+   |          +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:109:11
@@ -96,6 +128,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [ref x @ .., _, _] => {}
+   |          +++
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr
index 77702e145df..bfab13d42d2 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr
@@ -8,6 +8,10 @@ LL |         [.., ref _y] => {}
    |              ^^^^^^ value borrowed here after move
    |
    = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, ref _x] => {}
+   |                +++
 
 error[E0382]: borrow of partially moved value: `a[..]`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:23:14
@@ -19,6 +23,10 @@ LL |         [.., ref _y] => {}
    |              ^^^^^^ value borrowed here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, (ref _x, _)] => {}
+   |                 +++
 
 error[E0382]: borrow of moved value: `a[..].0`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:33:15
@@ -30,6 +38,10 @@ LL |         [.., (ref _y, _)] => {}
    |               ^^^^^^ value borrowed here after move
    |
    = note: move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, (ref _x, _)] => {}
+   |                 +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:44:11
@@ -41,6 +53,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [ref _x, _, _] => {}
+   |          +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:55:11
@@ -52,6 +68,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [.., ref _x] => {}
+   |              +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:66:11
@@ -63,6 +83,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [(ref _x, _), _, _] => {}
+   |           +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:77:11
@@ -74,6 +98,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [.., (ref _x, _)] => {}
+   |               +++
 
 error[E0382]: borrow of moved value: `a[..]`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:89:11
@@ -85,6 +113,10 @@ LL |         [(ref _x, _), _, _] => {}
    |           ^^^^^^ value borrowed here after move
    |
    = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [ref _y @ .., _, _] => {}
+   |          +++
 
 error[E0382]: borrow of moved value: `a[..]`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:99:15
@@ -96,6 +128,10 @@ LL |         [.., (ref _x, _)] => {}
    |               ^^^^^^ value borrowed here after move
    |
    = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, ref _y @ ..] => {}
+   |                +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:110:11
@@ -107,6 +143,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [ref x @ .., _] => {}
+   |          +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:123:5
@@ -118,6 +158,10 @@ LL |     a[2] = Default::default();
    |     ^^^^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, ref _x] => {}
+   |                +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:131:5
@@ -129,6 +173,10 @@ LL |     a[2].1 = Default::default();
    |     ^^^^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, (ref _x, _)] => {}
+   |                 +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:139:5
@@ -140,6 +188,10 @@ LL |     a[0] = Default::default();
    |     ^^^^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, ref _x @ ..] => {}
+   |                +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:147:5
@@ -151,6 +203,10 @@ LL |     a[0].1 = Default::default();
    |     ^^^^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, ref _x @ ..] => {}
+   |                +++
 
 error: aborting due to 14 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr
index 6cc2c2f7a98..8412c24fe61 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr
@@ -8,6 +8,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, ref _x] => {}
+   |                +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:28:11
@@ -19,6 +23,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, _, (ref _x, _)] => {}
+   |                 +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:41:11
@@ -30,6 +38,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [ref _x, _, _] => {}
+   |          +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:52:11
@@ -41,6 +53,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [.., ref _x] => {}
+   |              +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:63:11
@@ -52,6 +68,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [(ref _x, _), _, _] => {}
+   |           +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:74:11
@@ -63,6 +83,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [.., (ref _x, _)] => {}
+   |               +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:85:11
@@ -74,6 +98,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [_, ref _y @ ..] => {}
+   |             +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:96:11
@@ -85,6 +113,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [ref _y @ .., _] => {}
+   |          +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:109:11
@@ -96,6 +128,10 @@ LL |     match a {
    |           ^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         [ref x @ .., _, _] => {}
+   |          +++
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr
index 9add7553afa..e2aeaafc63c 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr
@@ -7,6 +7,10 @@ LL |     let [.., ref _y] = a;
    |              ^^^^^^ value borrowed here after move
    |
    = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [_, _, ref _x] = a;
+   |                +++
 
 error[E0382]: borrow of partially moved value: `a[..]`
   --> $DIR/borrowck-move-out-from-array-use.rs:16:14
@@ -17,6 +21,10 @@ LL |     let [.., ref _y] = a;
    |              ^^^^^^ value borrowed here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [_, _, (ref _x, _)] = a;
+   |                 +++
 
 error[E0382]: borrow of moved value: `a[..].0`
   --> $DIR/borrowck-move-out-from-array-use.rs:22:15
@@ -27,6 +35,10 @@ LL |     let [.., (ref _y, _)] = a;
    |               ^^^^^^ value borrowed here after move
    |
    = note: move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [_, _, (ref _x, _)] = a;
+   |                 +++
 
 error[E0382]: borrow of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:30:10
@@ -37,6 +49,10 @@ LL |     let [ref _y @ .., _, _] = a;
    |          ^^^^^^ value borrowed here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [ref _x, _, _] = a;
+   |          +++
 
 error[E0382]: borrow of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:36:16
@@ -47,6 +63,10 @@ LL |     let [_, _, ref _y @ ..] = a;
    |                ^^^^^^ value borrowed here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [.., ref _x] = a;
+   |              +++
 
 error[E0382]: borrow of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:42:10
@@ -57,6 +77,10 @@ LL |     let [ref _y @ .., _, _] = a;
    |          ^^^^^^ value borrowed here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [(ref _x, _), _, _] = a;
+   |           +++
 
 error[E0382]: borrow of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:48:16
@@ -67,6 +91,10 @@ LL |     let [_, _, ref _y @ ..] = a;
    |                ^^^^^^ value borrowed here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [.., (ref _x, _)] = a;
+   |               +++
 
 error[E0382]: borrow of moved value: `a[..]`
   --> $DIR/borrowck-move-out-from-array-use.rs:54:11
@@ -77,6 +105,10 @@ LL |     let [(ref _x, _), _, _] = a;
    |           ^^^^^^ value borrowed here after move
    |
    = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [ref _y @ .., _, _] = a;
+   |          +++
 
 error[E0382]: borrow of moved value: `a[..]`
   --> $DIR/borrowck-move-out-from-array-use.rs:60:15
@@ -87,6 +119,10 @@ LL |     let [.., (ref _x, _)] = a;
    |               ^^^^^^ value borrowed here after move
    |
    = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [_, _, ref _y @ ..] = a;
+   |                +++
 
 error[E0382]: borrow of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:68:13
@@ -97,6 +133,10 @@ LL |     let [_, ref _y @ ..] = a;
    |             ^^^^^^ value borrowed here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [ref x @ .., _] = a;
+   |          +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:76:5
@@ -107,6 +147,10 @@ LL |     a[2] = Default::default();
    |     ^^^^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [_, _, ref _x] = a;
+   |                +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:82:5
@@ -117,6 +161,10 @@ LL |     a[2].1 = Default::default();
    |     ^^^^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [_, _, (ref _x, _)] = a;
+   |                 +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:88:5
@@ -127,6 +175,10 @@ LL |     a[0] = Default::default();
    |     ^^^^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [_, _, ref _x @ ..] = a;
+   |                +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:94:5
@@ -137,6 +189,10 @@ LL |     a[0].1 = Default::default();
    |     ^^^^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [_, _, ref _x @ ..] = a;
+   |                +++
 
 error: aborting due to 14 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.stderr
index 363effcfe53..dd456681f57 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array.stderr
@@ -7,6 +7,10 @@ LL |     let [.., _y] = a;
    |              ^^ value used here after move
    |
    = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [_, _, ref _x] = a;
+   |                +++
 
 error[E0382]: use of partially moved value: `a[..]`
   --> $DIR/borrowck-move-out-from-array.rs:16:14
@@ -17,6 +21,10 @@ LL |     let [.., _y] = a;
    |              ^^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [_, _, (ref _x, _)] = a;
+   |                 +++
 
 error[E0382]: use of moved value: `a[..].0`
   --> $DIR/borrowck-move-out-from-array.rs:22:15
@@ -27,6 +35,10 @@ LL |     let [.., (_y, _)] = a;
    |               ^^ value used here after move
    |
    = note: move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [_, _, (ref _x, _)] = a;
+   |                 +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array.rs:30:10
@@ -37,6 +49,10 @@ LL |     let [_y @ .., _, _] = a;
    |          ^^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [ref _x, _, _] = a;
+   |          +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array.rs:36:16
@@ -47,6 +63,10 @@ LL |     let [_, _, _y @ ..] = a;
    |                ^^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [.., ref _x] = a;
+   |              +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array.rs:42:10
@@ -57,6 +77,10 @@ LL |     let [_y @ .., _, _] = a;
    |          ^^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [(ref _x, _), _, _] = a;
+   |           +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array.rs:48:16
@@ -67,6 +91,10 @@ LL |     let [_, _, _y @ ..] = a;
    |                ^^ value used here after partial move
    |
    = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [.., (ref _x, _)] = a;
+   |               +++
 
 error[E0382]: use of moved value: `a[..].0`
   --> $DIR/borrowck-move-out-from-array.rs:54:11
@@ -77,6 +105,10 @@ LL |     let [(_x, _), _, _] = a;
    |           ^^ value used here after move
    |
    = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [ref _y @ .., _, _] = a;
+   |          +++
 
 error[E0382]: use of moved value: `a[..].0`
   --> $DIR/borrowck-move-out-from-array.rs:60:15
@@ -87,6 +119,10 @@ LL |     let [.., (_x, _)] = a;
    |               ^^ value used here after move
    |
    = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [_, _, ref _y @ ..] = a;
+   |                +++
 
 error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array.rs:68:13
@@ -97,6 +133,10 @@ LL |     let [_, _y @ ..] = a;
    |             ^^ value used here after partial move
    |
    = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let [ref x @ .., _] = a;
+   |          +++
 
 error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-multiple-captures.stderr b/src/test/ui/borrowck/borrowck-multiple-captures.stderr
index 86d2955e236..f94cbc30db4 100644
--- a/src/test/ui/borrowck/borrowck-multiple-captures.stderr
+++ b/src/test/ui/borrowck/borrowck-multiple-captures.stderr
@@ -40,6 +40,11 @@ LL |     thread::spawn(move|| {
 ...
 LL |         drop(x1);
    |              -- use occurs due to use in closure
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     drop(x1.clone());
+   |            ++++++++
 
 error[E0382]: use of moved value: `x2`
   --> $DIR/borrowck-multiple-captures.rs:27:19
@@ -53,6 +58,11 @@ LL |     thread::spawn(move|| {
 ...
 LL |         drop(x2);
    |              -- use occurs due to use in closure
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     drop(x2.clone());
+   |            ++++++++
 
 error[E0382]: use of moved value: `x`
   --> $DIR/borrowck-multiple-captures.rs:41:14
@@ -100,6 +110,11 @@ LL |     thread::spawn(move|| {
 LL |
 LL |         drop(x);
    |              - use occurs due to use in closure
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     drop(x.clone());
+   |           ++++++++
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-move-index.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-move-index.stderr
index e01c26adcfc..fb0e274c291 100644
--- a/src/test/ui/borrowck/borrowck-overloaded-index-move-index.stderr
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-move-index.stderr
@@ -33,6 +33,11 @@ LL |     println!("{}", f[s]);
 ...
 LL |     f[s] = 10;
    |       ^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     println!("{}", f[s.clone()]);
+   |                       ++++++++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-reinit.stderr b/src/test/ui/borrowck/borrowck-reinit.stderr
index 22253cd96f1..f785900d53f 100644
--- a/src/test/ui/borrowck/borrowck-reinit.stderr
+++ b/src/test/ui/borrowck/borrowck-reinit.stderr
@@ -8,6 +8,11 @@ LL |     drop(x);
    |          - value moved here
 LL |     let _ = (1,x);
    |                ^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     drop(x.clone());
+   |           ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr b/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr
index d33115988a9..ad898fcabd9 100644
--- a/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr
+++ b/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr
@@ -8,6 +8,11 @@ LL |         Some(_) if { drop(a); false } => None,
    |                           - value moved here
 LL |         x => x,
    |         ^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         Some(_) if { drop(a.clone()); false } => None,
+   |                            ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr
index b20cc6d8cf5..716cc9d0c8b 100644
--- a/src/test/ui/borrowck/issue-41962.stderr
+++ b/src/test/ui/borrowck/issue-41962.stderr
@@ -5,7 +5,7 @@ LL |         if let Some(thing) = maybe {
    |                     ^^^^^ value moved here, in previous iteration of loop
    |
    = note: move occurs because value has type `Vec<bool>`, which does not implement the `Copy` trait
-help: borrow this field in the pattern to avoid moving `maybe.0`
+help: borrow this binding in the pattern to avoid moving the value
    |
 LL |         if let Some(ref thing) = maybe {
    |                     +++
diff --git a/src/test/ui/borrowck/issue-83760.stderr b/src/test/ui/borrowck/issue-83760.stderr
index beeda5685dc..2552fff860c 100644
--- a/src/test/ui/borrowck/issue-83760.stderr
+++ b/src/test/ui/borrowck/issue-83760.stderr
@@ -8,6 +8,10 @@ LL |             val = None;
    |             ---------- this reinitialization might get skipped
    |
    = note: move occurs because value has type `Struct`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     while let Some(ref foo) = val {
+   |                    +++
 
 error[E0382]: use of moved value: `foo`
   --> $DIR/issue-83760.rs:21:14
diff --git a/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr
index c6931ba7257..55948afca73 100644
--- a/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr
+++ b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr
@@ -5,7 +5,7 @@ LL |         if let Some(mut _x) = opt {}
    |                     ^^^^^^ value moved here, in previous iteration of loop
    |
    = note: move occurs because value has type `&mut i32`, which does not implement the `Copy` trait
-help: borrow this field in the pattern to avoid moving `opt.0`
+help: borrow this binding in the pattern to avoid moving the value
    |
 LL |         if let Some(ref mut _x) = opt {}
    |                     +++
diff --git a/src/test/ui/borrowck/move-in-pattern-mut.stderr b/src/test/ui/borrowck/move-in-pattern-mut.stderr
index 2bf34b32176..dd3471e2c8b 100644
--- a/src/test/ui/borrowck/move-in-pattern-mut.stderr
+++ b/src/test/ui/borrowck/move-in-pattern-mut.stderr
@@ -8,7 +8,7 @@ LL |     foo(s);
    |         ^ value used here after partial move
    |
    = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait
-help: borrow this field in the pattern to avoid moving `s.0`
+help: borrow this binding in the pattern to avoid moving the value
    |
 LL |     if let Some(ref mut x) = s {
    |                 +++
@@ -23,7 +23,7 @@ LL |     bar(e);
    |         ^ value used here after partial move
    |
    = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait
-help: borrow this field in the pattern to avoid moving `e.s`
+help: borrow this binding in the pattern to avoid moving the value
    |
 LL |     let E::V { s: ref mut x } = e;
    |                   +++
diff --git a/src/test/ui/borrowck/move-in-pattern.stderr b/src/test/ui/borrowck/move-in-pattern.stderr
index 6b84c0032cd..250acbe5928 100644
--- a/src/test/ui/borrowck/move-in-pattern.stderr
+++ b/src/test/ui/borrowck/move-in-pattern.stderr
@@ -8,7 +8,7 @@ LL |     foo(s);
    |         ^ value used here after partial move
    |
    = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait
-help: borrow this field in the pattern to avoid moving `s.0`
+help: borrow this binding in the pattern to avoid moving the value
    |
 LL |     if let Some(ref x) = s {
    |                 +++
@@ -23,7 +23,7 @@ LL |     bar(e);
    |         ^ value used here after partial move
    |
    = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait
-help: borrow this field in the pattern to avoid moving `e.s`
+help: borrow this binding in the pattern to avoid moving the value
    |
 LL |     let E::V { s: ref x } = e;
    |                   +++
diff --git a/src/test/ui/borrowck/mut-borrow-in-loop-2.stderr b/src/test/ui/borrowck/mut-borrow-in-loop-2.stderr
index 8b05b238822..74e7067c9af 100644
--- a/src/test/ui/borrowck/mut-borrow-in-loop-2.stderr
+++ b/src/test/ui/borrowck/mut-borrow-in-loop-2.stderr
@@ -4,9 +4,17 @@ error[E0382]: use of moved value: `value`
 LL | fn this_does_not<'a, R>(value: &'a mut Events<R>) {
    |                         ----- move occurs because `value` has type `&mut Events<R>`, which does not implement the `Copy` trait
 LL |     for _ in 0..3 {
+   |     ------------- inside of this loop
 LL |         Other::handle(value);
    |                       ^^^^^ value moved here, in previous iteration of loop
    |
+note: consider changing this parameter type in function `handle` to borrow instead if owning the value isn't necessary
+  --> $DIR/mut-borrow-in-loop-2.rs:9:22
+   |
+LL |     fn handle(value: T) -> Self;
+   |        ------        ^ this parameter takes ownership of the value
+   |        |
+   |        in this function
 help: consider creating a fresh reborrow of `value` here
    |
 LL |         Other::handle(&mut *value);
diff --git a/src/test/ui/borrowck/or-patterns.stderr b/src/test/ui/borrowck/or-patterns.stderr
index dd5797c3f79..9501798bb06 100644
--- a/src/test/ui/borrowck/or-patterns.stderr
+++ b/src/test/ui/borrowck/or-patterns.stderr
@@ -8,6 +8,10 @@ LL |     &x.0 .0;
    |     ^^^^^^^ value borrowed here after move
    |
    = note: move occurs because `x.0.0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ((ref y, _) | (_, y),) => (),
+   |           +++
 
 error[E0382]: borrow of moved value: `x.0.1`
   --> $DIR/or-patterns.rs:10:5
@@ -19,6 +23,10 @@ LL |     &x.0 .1;
    |     ^^^^^^^ value borrowed here after move
    |
    = note: move occurs because `x.0.1` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ((y, _) | (_, ref y),) => (),
+   |                       +++
 
 error[E0502]: cannot borrow `x.0.0` as mutable because it is also borrowed as immutable
   --> $DIR/or-patterns.rs:18:5
@@ -77,6 +85,10 @@ LL |     &x.0 .0;
    |     ^^^^^^^ value borrowed here after move
    |
    = note: move occurs because `x.0.0` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ((ref y, _) | (_, y),) = x;
+   |           +++
 
 error[E0382]: borrow of moved value: `x.0.1`
   --> $DIR/or-patterns.rs:40:5
@@ -88,6 +100,10 @@ LL |     &x.0 .1;
    |     ^^^^^^^ value borrowed here after move
    |
    = note: move occurs because `x.0.1` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ((y, _) | (_, ref y),) = x;
+   |                       +++
 
 error[E0502]: cannot borrow `x.0.0` as mutable because it is also borrowed as immutable
   --> $DIR/or-patterns.rs:46:5
diff --git a/src/test/ui/chalkify/bugs/async.stderr b/src/test/ui/chalkify/bugs/async.stderr
index f53ed53f73c..6f22d2c593a 100644
--- a/src/test/ui/chalkify/bugs/async.stderr
+++ b/src/test/ui/chalkify/bugs/async.stderr
@@ -1,32 +1,47 @@
-error[E0277]: the trait bound `[static generator@$DIR/async.rs:7:29: 9:2]: Generator<ResumeTy>` is not satisfied
+error[E0277]: `impl Future<Output = u32>` is not a future
   --> $DIR/async.rs:7:29
    |
 LL |   async fn foo(x: u32) -> u32 {
-   |  _____________________________^
+   |  _____________________________-
 LL | |     x
 LL | | }
-   | |_^ the trait `Generator<ResumeTy>` is not implemented for `[static generator@$DIR/async.rs:7:29: 9:2]`
+   | | ^
+   | | |
+   | |_`impl Future<Output = u32>` is not a future
+   |   required by a bound introduced by this call
    |
-note: required by a bound in `std::future::from_generator`
+   = help: the trait `Future` is not implemented for `impl Future<Output = u32>`
+   = note: impl Future<Output = u32> must be a future or must implement `IntoFuture` to be awaited
+note: required by a bound in `identity_future`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
-LL |     T: Generator<ResumeTy, Yield = ()>,
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `std::future::from_generator`
+LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
+   |                                      ^^^^^^^^^^^^^^^^^^ required by this bound in `identity_future`
 
-error[E0280]: the requirement `<[static generator@$DIR/async.rs:7:29: 9:2] as Generator<ResumeTy>>::Yield == ()` is not satisfied
+error[E0277]: the size for values of type `<impl Future<Output = u32> as Future>::Output` cannot be known at compilation time
   --> $DIR/async.rs:7:29
    |
 LL |   async fn foo(x: u32) -> u32 {
    |  _____________________________^
 LL | |     x
 LL | | }
-   | |_^
+   | |_^ doesn't have a size known at compile-time
    |
-note: required by a bound in `std::future::from_generator`
+   = help: the trait `Sized` is not implemented for `<impl Future<Output = u32> as Future>::Output`
+note: required by a bound in `identity_future`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
-LL |     T: Generator<ResumeTy, Yield = ()>,
-   |                            ^^^^^^^^^^ required by this bound in `std::future::from_generator`
+LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
+   |                              ^ required by this bound in `identity_future`
+
+error[E0277]: `impl Future<Output = u32>` is not a future
+  --> $DIR/async.rs:7:25
+   |
+LL | async fn foo(x: u32) -> u32 {
+   |                         ^^^ `impl Future<Output = u32>` is not a future
+   |
+   = help: the trait `Future` is not implemented for `impl Future<Output = u32>`
+   = note: impl Future<Output = u32> must be a future or must implement `IntoFuture` to be awaited
 
 error[E0280]: the requirement `<impl Future<Output = u32> as Future>::Output == u32` is not satisfied
   --> $DIR/async.rs:7:25
@@ -34,6 +49,6 @@ error[E0280]: the requirement `<impl Future<Output = u32> as Future>::Output ==
 LL | async fn foo(x: u32) -> u32 {
    |                         ^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/check-cfg/well-known-values.stderr b/src/test/ui/check-cfg/well-known-values.stderr
index 6c0dc05ba23..29ececea5d3 100644
--- a/src/test/ui/check-cfg/well-known-values.stderr
+++ b/src/test/ui/check-cfg/well-known-values.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(target_os = "linuz")]
    |                   |
    |                   help: did you mean: `"linux"`
    |
-   = note: expected values for `target_os` are: android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, nto, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, watchos, windows, xous
+   = note: expected values for `target_os` are: aix, android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, nto, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, watchos, windows, xous
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value
diff --git a/src/test/ui/codemap_tests/tab_3.stderr b/src/test/ui/codemap_tests/tab_3.stderr
index 9072cc925ff..080f6c39449 100644
--- a/src/test/ui/codemap_tests/tab_3.stderr
+++ b/src/test/ui/codemap_tests/tab_3.stderr
@@ -15,6 +15,10 @@ note: this function takes ownership of the receiver `self`, which moves `some_ve
 LL |     fn into_iter(self) -> Self::IntoIter;
    |                  ^^^^
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     some_vec.clone().into_iter();
+   |             ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/coherence/coherence-with-closure.rs b/src/test/ui/coherence/coherence-with-closure.rs
index 6e3281d8508..5b6a62b24d4 100644
--- a/src/test/ui/coherence/coherence-with-closure.rs
+++ b/src/test/ui/coherence/coherence-with-closure.rs
@@ -8,7 +8,6 @@ fn defining_use() -> OpaqueClosure {
 struct Wrapper<T>(T);
 trait Trait {}
 impl Trait for Wrapper<OpaqueClosure> {}
-//~^ ERROR cannot implement trait on type alias impl trait
 impl<T: Sync> Trait for Wrapper<T> {}
 //~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
 
diff --git a/src/test/ui/coherence/coherence-with-closure.stderr b/src/test/ui/coherence/coherence-with-closure.stderr
index d2ca63fa146..431108e14d7 100644
--- a/src/test/ui/coherence/coherence-with-closure.stderr
+++ b/src/test/ui/coherence/coherence-with-closure.stderr
@@ -1,24 +1,11 @@
 error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
-  --> $DIR/coherence-with-closure.rs:12:1
+  --> $DIR/coherence-with-closure.rs:11:1
    |
 LL | impl Trait for Wrapper<OpaqueClosure> {}
    | ------------------------------------- first implementation here
-LL |
 LL | impl<T: Sync> Trait for Wrapper<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueClosure>`
 
-error: cannot implement trait on type alias impl trait
-  --> $DIR/coherence-with-closure.rs:10:24
-   |
-LL | impl Trait for Wrapper<OpaqueClosure> {}
-   |                        ^^^^^^^^^^^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/coherence-with-closure.rs:3:22
-   |
-LL | type OpaqueClosure = impl Sized;
-   |                      ^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-with-generator.rs b/src/test/ui/coherence/coherence-with-generator.rs
index d34c391db9f..70665ba06f9 100644
--- a/src/test/ui/coherence/coherence-with-generator.rs
+++ b/src/test/ui/coherence/coherence-with-generator.rs
@@ -12,7 +12,6 @@ fn defining_use() -> OpaqueGenerator {
 struct Wrapper<T>(T);
 trait Trait {}
 impl Trait for Wrapper<OpaqueGenerator> {}
-//~^ ERROR cannot implement trait on type alias impl trait
 impl<T: Sync> Trait for Wrapper<T> {}
 //~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
 
diff --git a/src/test/ui/coherence/coherence-with-generator.stderr b/src/test/ui/coherence/coherence-with-generator.stderr
index 804bc1c3a6d..6d3be2e16c6 100644
--- a/src/test/ui/coherence/coherence-with-generator.stderr
+++ b/src/test/ui/coherence/coherence-with-generator.stderr
@@ -1,24 +1,11 @@
 error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
-  --> $DIR/coherence-with-generator.rs:16:1
+  --> $DIR/coherence-with-generator.rs:15:1
    |
 LL | impl Trait for Wrapper<OpaqueGenerator> {}
    | --------------------------------------- first implementation here
-LL |
 LL | impl<T: Sync> Trait for Wrapper<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueGenerator>`
 
-error: cannot implement trait on type alias impl trait
-  --> $DIR/coherence-with-generator.rs:14:24
-   |
-LL | impl Trait for Wrapper<OpaqueGenerator> {}
-   |                        ^^^^^^^^^^^^^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/coherence-with-generator.rs:3:24
-   |
-LL | type OpaqueGenerator = impl Sized;
-   |                        ^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/const-generics/projection-as-arg-const.rs b/src/test/ui/const-generics/projection-as-arg-const.rs
new file mode 100644
index 00000000000..903548c75db
--- /dev/null
+++ b/src/test/ui/const-generics/projection-as-arg-const.rs
@@ -0,0 +1,20 @@
+// This is currently not possible to use projections as const generics.
+// More information about this available here:
+// https://github.com/rust-lang/rust/pull/104443#discussion_r1029375633
+
+pub trait Identity {
+    type Identity;
+}
+
+impl<T> Identity for T {
+    type Identity = Self;
+}
+
+pub fn foo<const X: <i32 as Identity>::Identity>() {
+//~^ ERROR
+    assert!(X == 12);
+}
+
+fn main() {
+    foo::<12>();
+}
diff --git a/src/test/ui/const-generics/projection-as-arg-const.stderr b/src/test/ui/const-generics/projection-as-arg-const.stderr
new file mode 100644
index 00000000000..803ed9c9597
--- /dev/null
+++ b/src/test/ui/const-generics/projection-as-arg-const.stderr
@@ -0,0 +1,11 @@
+error: `<i32 as Identity>::Identity` is forbidden as the type of a const generic parameter
+  --> $DIR/projection-as-arg-const.rs:13:21
+   |
+LL | pub fn foo<const X: <i32 as Identity>::Identity>() {
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-eval/infinite_loop.rs b/src/test/ui/consts/const-eval/infinite_loop.rs
index 14a573ccf5a..4babc9a2850 100644
--- a/src/test/ui/consts/const-eval/infinite_loop.rs
+++ b/src/test/ui/consts/const-eval/infinite_loop.rs
@@ -4,8 +4,8 @@ fn main() {
     let _ = [(); {
         let mut n = 113383; // #20 in https://oeis.org/A006884
         while n != 0 {
-            n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
             //~^ ERROR evaluation of constant value failed
+            n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
         }
         n
     }];
diff --git a/src/test/ui/consts/const-eval/infinite_loop.stderr b/src/test/ui/consts/const-eval/infinite_loop.stderr
index 3b5a0f22f28..8b58cb279f3 100644
--- a/src/test/ui/consts/const-eval/infinite_loop.stderr
+++ b/src/test/ui/consts/const-eval/infinite_loop.stderr
@@ -1,8 +1,8 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/infinite_loop.rs:7:20
+  --> $DIR/infinite_loop.rs:6:15
    |
-LL |             n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
-   |                    ^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+LL |         while n != 0 {
+   |               ^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/issue-104768.rs b/src/test/ui/consts/issue-104768.rs
new file mode 100644
index 00000000000..3192daafa0b
--- /dev/null
+++ b/src/test/ui/consts/issue-104768.rs
@@ -0,0 +1,4 @@
+const A: &_ = 0_u32;
+//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for constants
+
+fn main() {}
diff --git a/src/test/ui/consts/issue-104768.stderr b/src/test/ui/consts/issue-104768.stderr
new file mode 100644
index 00000000000..55b2b6f0435
--- /dev/null
+++ b/src/test/ui/consts/issue-104768.stderr
@@ -0,0 +1,12 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/issue-104768.rs:1:10
+   |
+LL | const A: &_ = 0_u32;
+   |          ^^
+   |          |
+   |          not allowed in type signatures
+   |          help: replace with the correct type: `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/drop/repeat-drop-2.stderr b/src/test/ui/drop/repeat-drop-2.stderr
index 7357551c4a7..f030228f71a 100644
--- a/src/test/ui/drop/repeat-drop-2.stderr
+++ b/src/test/ui/drop/repeat-drop-2.stderr
@@ -7,6 +7,11 @@ LL |     let _bar = foo;
    |                --- value moved here
 LL |     let _baz = [foo; 0];
    |                 ^^^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _bar = foo.clone();
+   |                   ++++++++
 
 error[E0493]: destructor of `String` cannot be evaluated at compile-time
   --> $DIR/repeat-drop-2.rs:7:25
diff --git a/src/test/ui/dyn-star/dispatch-on-pin-mut.rs b/src/test/ui/dyn-star/dispatch-on-pin-mut.rs
new file mode 100644
index 00000000000..5774c8b2a67
--- /dev/null
+++ b/src/test/ui/dyn-star/dispatch-on-pin-mut.rs
@@ -0,0 +1,52 @@
+// run-pass
+// edition:2021
+// check-run-results
+
+#![feature(dyn_star)]
+//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+
+use std::future::Future;
+
+async fn foo(f: dyn* Future<Output = i32>) {
+    println!("value: {}", f.await);
+}
+
+async fn async_main() {
+    foo(Box::pin(async { 1 })).await
+}
+
+// ------------------------------------------------------------------------- //
+// Implementation Details Below...
+
+use std::pin::Pin;
+use std::task::*;
+
+pub fn noop_waker() -> Waker {
+    let raw = RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE);
+
+    // SAFETY: the contracts for RawWaker and RawWakerVTable are upheld
+    unsafe { Waker::from_raw(raw) }
+}
+
+const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
+
+unsafe fn noop_clone(_p: *const ()) -> RawWaker {
+    RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE)
+}
+
+unsafe fn noop(_p: *const ()) {}
+
+fn main() {
+    let mut fut = async_main();
+
+    // Poll loop, just to test the future...
+    let waker = noop_waker();
+    let ctx = &mut Context::from_waker(&waker);
+
+    loop {
+        match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } {
+            Poll::Pending => {}
+            Poll::Ready(()) => break,
+        }
+    }
+}
diff --git a/src/test/ui/dyn-star/dispatch-on-pin-mut.run.stdout b/src/test/ui/dyn-star/dispatch-on-pin-mut.run.stdout
new file mode 100644
index 00000000000..96c5ca6985f
--- /dev/null
+++ b/src/test/ui/dyn-star/dispatch-on-pin-mut.run.stdout
@@ -0,0 +1 @@
+value: 1
diff --git a/src/test/ui/dyn-star/dispatch-on-pin-mut.stderr b/src/test/ui/dyn-star/dispatch-on-pin-mut.stderr
new file mode 100644
index 00000000000..fdf74aa7efe
--- /dev/null
+++ b/src/test/ui/dyn-star/dispatch-on-pin-mut.stderr
@@ -0,0 +1,11 @@
+warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/dispatch-on-pin-mut.rs:5:12
+   |
+LL | #![feature(dyn_star)]
+   |            ^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.rs b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.rs
index b4ff8a22286..c12b16f1605 100644
--- a/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.rs
+++ b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.rs
@@ -1,7 +1,8 @@
-// check-pass
+// run-pass
+// check-run-results
 
 #![feature(dyn_star)]
-#![allow(incomplete_features)]
+//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
 
 trait AddOne {
     fn add1(&mut self) -> usize;
diff --git a/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.run.stdout b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.run.stdout
new file mode 100644
index 00000000000..b4db3ed707d
--- /dev/null
+++ b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.run.stdout
@@ -0,0 +1,2 @@
+43
+44
diff --git a/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr
new file mode 100644
index 00000000000..933c133831a
--- /dev/null
+++ b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr
@@ -0,0 +1,11 @@
+warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/dont-unsize-coerce-dyn-star.rs:4:12
+   |
+LL | #![feature(dyn_star)]
+   |            ^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.rs b/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.rs
new file mode 100644
index 00000000000..a4eb669e321
--- /dev/null
+++ b/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.rs
@@ -0,0 +1,13 @@
+#![feature(dyn_star, trait_upcasting)]
+//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+
+trait A: B {}
+trait B {}
+impl A for usize {}
+impl B for usize {}
+
+fn main() {
+    let x: Box<dyn* A> = Box::new(1usize as dyn* A);
+    let y: Box<dyn* B> = x;
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr b/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr
new file mode 100644
index 00000000000..2fc751b3b4a
--- /dev/null
+++ b/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr
@@ -0,0 +1,23 @@
+warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/no-unsize-coerce-dyn-trait.rs:1:12
+   |
+LL | #![feature(dyn_star, trait_upcasting)]
+   |            ^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/no-unsize-coerce-dyn-trait.rs:11:26
+   |
+LL |     let y: Box<dyn* B> = x;
+   |            -----------   ^ expected trait `B`, found trait `A`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `Box<dyn* B>`
+              found struct `Box<dyn* A>`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/dyn-star/upcast.rs b/src/test/ui/dyn-star/upcast.rs
index cee76ada7df..c667ac143a3 100644
--- a/src/test/ui/dyn-star/upcast.rs
+++ b/src/test/ui/dyn-star/upcast.rs
@@ -1,7 +1,6 @@
-// run-pass
+// known-bug: #104800
 
 #![feature(dyn_star, trait_upcasting)]
-#![allow(incomplete_features)]
 
 trait Foo: Bar {
     fn hello(&self);
diff --git a/src/test/ui/dyn-star/upcast.stderr b/src/test/ui/dyn-star/upcast.stderr
new file mode 100644
index 00000000000..6a95f7754e6
--- /dev/null
+++ b/src/test/ui/dyn-star/upcast.stderr
@@ -0,0 +1,20 @@
+warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/upcast.rs:3:12
+   |
+LL | #![feature(dyn_star, trait_upcasting)]
+   |            ^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: `dyn* Foo` needs to be a pointer-sized type
+  --> $DIR/upcast.rs:30:23
+   |
+LL |     let w: dyn* Bar = w;
+   |                       ^ `dyn* Foo` needs to be a pointer-sized type
+   |
+   = help: the trait `PointerSized` is not implemented for `dyn* Foo`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/empty/empty-struct-braces-expr.rs b/src/test/ui/empty/empty-struct-braces-expr.rs
index f4144277f16..2aab3e7772c 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.rs
+++ b/src/test/ui/empty/empty-struct-braces-expr.rs
@@ -17,7 +17,7 @@ fn main() {
     //~^ ERROR expected function, tuple struct or tuple variant, found struct `Empty1`
     let e3 = E::Empty3; //~ ERROR expected value, found struct variant `E::Empty3`
     let e3 = E::Empty3();
-    //~^ ERROR expected function, tuple struct or tuple variant, found struct variant `E::Empty3`
+    //~^ ERROR expected value, found struct variant `E::Empty3`
 
     let xe1 = XEmpty1; //~ ERROR expected value, found struct `XEmpty1`
     let xe1 = XEmpty1();
diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr
index 5b0ca613fc4..e1a7a02a568 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.stderr
+++ b/src/test/ui/empty/empty-struct-braces-expr.stderr
@@ -21,24 +21,6 @@ help: a unit struct with a similar name exists
 LL |     let e1 = XEmpty2;
    |              ~~~~~~~
 
-error[E0423]: expected value, found struct variant `E::Empty3`
-  --> $DIR/empty-struct-braces-expr.rs:18:14
-   |
-LL |     Empty3 {}
-   |     --------- `E::Empty3` defined here
-...
-LL |     let e3 = E::Empty3;
-   |              ^^^^^^^^^ help: use struct literal syntax instead: `E::Empty3 {}`
-
-error[E0423]: expected function, tuple struct or tuple variant, found struct variant `E::Empty3`
-  --> $DIR/empty-struct-braces-expr.rs:19:14
-   |
-LL |     Empty3 {}
-   |     --------- `E::Empty3` defined here
-...
-LL |     let e3 = E::Empty3();
-   |              ^^^^^^^^^^^ help: use struct literal syntax instead: `E::Empty3 {}`
-
 error[E0423]: expected value, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-expr.rs:22:15
    |
@@ -84,6 +66,18 @@ help: a unit struct with a similar name exists
 LL |     let e1 = XEmpty2();
    |              ~~~~~~~
 
+error[E0533]: expected value, found struct variant `E::Empty3`
+  --> $DIR/empty-struct-braces-expr.rs:18:14
+   |
+LL |     let e3 = E::Empty3;
+   |              ^^^^^^^^^ not a value
+
+error[E0533]: expected value, found struct variant `E::Empty3`
+  --> $DIR/empty-struct-braces-expr.rs:19:14
+   |
+LL |     let e3 = E::Empty3();
+   |              ^^^^^^^^^ not a value
+
 error[E0423]: expected function, tuple struct or tuple variant, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-expr.rs:23:15
    |
@@ -132,5 +126,5 @@ LL |     XE::Empty1 {};
 
 error: aborting due to 9 previous errors
 
-Some errors have detailed explanations: E0423, E0599.
+Some errors have detailed explanations: E0423, E0533, E0599.
 For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/empty/empty-struct-braces-pat-1.stderr b/src/test/ui/empty/empty-struct-braces-pat-1.stderr
index 0215a9e5935..14e09fc27a0 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-1.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-1.stderr
@@ -1,34 +1,15 @@
-error[E0532]: expected unit struct, unit variant or constant, found struct variant `E::Empty3`
+error[E0533]: expected unit struct, unit variant or constant, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-pat-1.rs:24:9
    |
-LL |     Empty3 {}
-   |     --------- `E::Empty3` defined here
-...
 LL |         E::Empty3 => ()
-   |         ^^^^^^^^^ help: use struct pattern syntax instead: `E::Empty3 {}`
+   |         ^^^^^^^^^ not a unit struct, unit variant or constant
 
-error[E0532]: expected unit struct, unit variant or constant, found struct variant `XE::XEmpty3`
+error[E0533]: expected unit struct, unit variant or constant, found struct variant `XE::XEmpty3`
   --> $DIR/empty-struct-braces-pat-1.rs:31:9
    |
 LL |         XE::XEmpty3 => ()
-   |         ^^^^^^^^^^^
-   |
-  ::: $DIR/auxiliary/empty-struct.rs:6:5
-   |
-LL |     XEmpty3 {},
-   |     ------- `XE::XEmpty3` defined here
-LL |     XEmpty4,
-   |     ------- similarly named unit variant `XEmpty4` defined here
-   |
-help: use struct pattern syntax instead
-   |
-LL |         XE::XEmpty3 { /* fields */ } => ()
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: a unit variant with a similar name exists
-   |
-LL |         XE::XEmpty4 => ()
-   |             ~~~~~~~
+   |         ^^^^^^^^^^^ not a unit struct, unit variant or constant
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0532`.
+For more information about this error, try `rustc --explain E0533`.
diff --git a/src/test/ui/empty/empty-struct-braces-pat-3.stderr b/src/test/ui/empty/empty-struct-braces-pat-3.stderr
index 615e7fb4aae..00c8b12e6f9 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-3.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-3.stderr
@@ -1,67 +1,27 @@
-error[E0532]: expected tuple struct or tuple variant, found struct variant `E::Empty3`
+error[E0164]: expected tuple struct or tuple variant, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-pat-3.rs:17:9
    |
-LL |     Empty3 {}
-   |     --------- `E::Empty3` defined here
-...
 LL |         E::Empty3() => ()
-   |         ^^^^^^^^^^^ help: use struct pattern syntax instead: `E::Empty3 {}`
+   |         ^^^^^^^^^^^ not a tuple struct or tuple variant
 
-error[E0532]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3`
+error[E0164]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3`
   --> $DIR/empty-struct-braces-pat-3.rs:21:9
    |
 LL |         XE::XEmpty3() => ()
-   |         ^^^^^^^^^^^^^
-   |
-  ::: $DIR/auxiliary/empty-struct.rs:6:5
-   |
-LL |     XEmpty3 {},
-   |     ------- `XE::XEmpty3` defined here
-LL |     XEmpty4,
-LL |     XEmpty5(),
-   |     ------- similarly named tuple variant `XEmpty5` defined here
-   |
-help: use struct pattern syntax instead
-   |
-LL |         XE::XEmpty3 { /* fields */ } => ()
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: a tuple variant with a similar name exists
-   |
-LL |         XE::XEmpty5() => ()
-   |             ~~~~~~~
+   |         ^^^^^^^^^^^^^ not a tuple struct or tuple variant
 
-error[E0532]: expected tuple struct or tuple variant, found struct variant `E::Empty3`
+error[E0164]: expected tuple struct or tuple variant, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-pat-3.rs:25:9
    |
-LL |     Empty3 {}
-   |     --------- `E::Empty3` defined here
-...
 LL |         E::Empty3(..) => ()
-   |         ^^^^^^^^^^^^^ help: use struct pattern syntax instead: `E::Empty3 {}`
+   |         ^^^^^^^^^^^^^ not a tuple struct or tuple variant
 
-error[E0532]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3`
+error[E0164]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3`
   --> $DIR/empty-struct-braces-pat-3.rs:29:9
    |
 LL |         XE::XEmpty3(..) => ()
-   |         ^^^^^^^^^^^^^^^
-   |
-  ::: $DIR/auxiliary/empty-struct.rs:6:5
-   |
-LL |     XEmpty3 {},
-   |     ------- `XE::XEmpty3` defined here
-LL |     XEmpty4,
-LL |     XEmpty5(),
-   |     ------- similarly named tuple variant `XEmpty5` defined here
-   |
-help: use struct pattern syntax instead
-   |
-LL |         XE::XEmpty3 { /* fields */ } => ()
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: a tuple variant with a similar name exists
-   |
-LL |         XE::XEmpty5(..) => ()
-   |             ~~~~~~~
+   |         ^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0532`.
+For more information about this error, try `rustc --explain E0164`.
diff --git a/src/test/ui/error-codes/E0164.stderr b/src/test/ui/error-codes/E0164.stderr
index 0db89dfec84..5a80d6ec31a 100644
--- a/src/test/ui/error-codes/E0164.stderr
+++ b/src/test/ui/error-codes/E0164.stderr
@@ -2,7 +2,7 @@ error[E0164]: expected tuple struct or tuple variant, found associated constant
   --> $DIR/E0164.rs:9:9
    |
 LL |         Foo::B(i) => i,
-   |         ^^^^^^^^^ not a tuple variant or struct
+   |         ^^^^^^^^^ not a tuple struct or tuple variant
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/errors/issue-104621-extern-bad-file.rs b/src/test/ui/errors/issue-104621-extern-bad-file.rs
new file mode 100644
index 00000000000..3f13d605232
--- /dev/null
+++ b/src/test/ui/errors/issue-104621-extern-bad-file.rs
@@ -0,0 +1,8 @@
+// compile-flags: --extern foo={{src-base}}/errors/issue-104621-extern-bad-file.rs
+// only-linux
+
+extern crate foo;
+//~^ ERROR extern location for foo is of an unknown type
+//~| ERROR file name should be lib*.rlib or lib*.so
+//~| ERROR can't find crate for `foo` [E0463]
+fn main() {}
diff --git a/src/test/ui/errors/issue-104621-extern-bad-file.stderr b/src/test/ui/errors/issue-104621-extern-bad-file.stderr
new file mode 100644
index 00000000000..b8500ad0e04
--- /dev/null
+++ b/src/test/ui/errors/issue-104621-extern-bad-file.stderr
@@ -0,0 +1,21 @@
+error: extern location for foo is of an unknown type: $DIR/issue-104621-extern-bad-file.rs
+  --> $DIR/issue-104621-extern-bad-file.rs:4:1
+   |
+LL | extern crate foo;
+   | ^^^^^^^^^^^^^^^^^
+
+error: file name should be lib*.rlib or lib*.so
+  --> $DIR/issue-104621-extern-bad-file.rs:4:1
+   |
+LL | extern crate foo;
+   | ^^^^^^^^^^^^^^^^^
+
+error[E0463]: can't find crate for `foo`
+  --> $DIR/issue-104621-extern-bad-file.rs:4:1
+   |
+LL | extern crate foo;
+   | ^^^^^^^^^^^^^^^^^ can't find crate
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0463`.
diff --git a/src/test/ui/errors/issue-104621-extern-not-file.rs b/src/test/ui/errors/issue-104621-extern-not-file.rs
new file mode 100644
index 00000000000..899e45a306b
--- /dev/null
+++ b/src/test/ui/errors/issue-104621-extern-not-file.rs
@@ -0,0 +1,4 @@
+// compile-flags: --extern foo=.
+
+extern crate foo; //~ ERROR extern location for foo is not a file: .
+fn main() {}
diff --git a/src/test/ui/errors/issue-104621-extern-not-file.stderr b/src/test/ui/errors/issue-104621-extern-not-file.stderr
new file mode 100644
index 00000000000..5aaf9741360
--- /dev/null
+++ b/src/test/ui/errors/issue-104621-extern-not-file.stderr
@@ -0,0 +1,8 @@
+error: extern location for foo is not a file: .
+  --> $DIR/issue-104621-extern-not-file.rs:3:1
+   |
+LL | extern crate foo;
+   | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/auto-trait.rs b/src/test/ui/impl-trait/auto-trait.rs
index afa95645a27..35994e4a5ba 100644
--- a/src/test/ui/impl-trait/auto-trait.rs
+++ b/src/test/ui/impl-trait/auto-trait.rs
@@ -20,7 +20,6 @@ impl<T: Send> AnotherTrait for T {}
 // in the future.)
 impl AnotherTrait for D<OpaqueType> {
     //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
-    //~| ERROR cannot implement trait on type alias impl trait
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/auto-trait.stderr b/src/test/ui/impl-trait/auto-trait.stderr
index 5e10272b0db..81009413c9a 100644
--- a/src/test/ui/impl-trait/auto-trait.stderr
+++ b/src/test/ui/impl-trait/auto-trait.stderr
@@ -7,18 +7,6 @@ LL | impl<T: Send> AnotherTrait for T {}
 LL | impl AnotherTrait for D<OpaqueType> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
 
-error: cannot implement trait on type alias impl trait
-  --> $DIR/auto-trait.rs:21:25
-   |
-LL | impl AnotherTrait for D<OpaqueType> {
-   |                         ^^^^^^^^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/auto-trait.rs:7:19
-   |
-LL | type OpaqueType = impl OpaqueTrait;
-   |                   ^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs b/src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs
new file mode 100644
index 00000000000..0bbe50ea6fd
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs
@@ -0,0 +1,17 @@
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+struct S;
+
+trait Foo {
+    fn bar<T>() -> impl Sized;
+}
+
+impl Foo for S {
+    fn bar() -> impl Sized {}
+    //~^ ERROR method `bar` has 0 type parameters but its trait declaration has 1 type parameter
+}
+
+fn main() {
+    S::bar();
+}
diff --git a/src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr b/src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr
new file mode 100644
index 00000000000..8ff54cad951
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr
@@ -0,0 +1,12 @@
+error[E0049]: method `bar` has 0 type parameters but its trait declaration has 1 type parameter
+  --> $DIR/trait-more-generics-than-impl.rs:11:11
+   |
+LL |     fn bar<T>() -> impl Sized;
+   |            - expected 1 type parameter
+...
+LL |     fn bar() -> impl Sized {}
+   |           ^ found 0 type parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0049`.
diff --git a/src/test/ui/impl-trait/negative-reasoning.rs b/src/test/ui/impl-trait/negative-reasoning.rs
index da69bb349ae..70e24a3a9d0 100644
--- a/src/test/ui/impl-trait/negative-reasoning.rs
+++ b/src/test/ui/impl-trait/negative-reasoning.rs
@@ -18,7 +18,6 @@ impl<T: std::fmt::Debug> AnotherTrait for T {}
 // This is in error, because we cannot assume that `OpaqueType: !Debug`
 impl AnotherTrait for D<OpaqueType> {
     //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
-    //~| ERROR cannot implement trait on type alias impl trait
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/negative-reasoning.stderr b/src/test/ui/impl-trait/negative-reasoning.stderr
index 479b451855d..6b8cc9e7374 100644
--- a/src/test/ui/impl-trait/negative-reasoning.stderr
+++ b/src/test/ui/impl-trait/negative-reasoning.stderr
@@ -9,18 +9,6 @@ LL | impl AnotherTrait for D<OpaqueType> {
    |
    = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions
 
-error: cannot implement trait on type alias impl trait
-  --> $DIR/negative-reasoning.rs:19:25
-   |
-LL | impl AnotherTrait for D<OpaqueType> {
-   |                         ^^^^^^^^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/negative-reasoning.rs:7:19
-   |
-LL | type OpaqueType = impl OpaqueTrait;
-   |                   ^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
index 621c4ea6e0d..af9dfe25bb4 100644
--- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
@@ -5,13 +5,13 @@ type Foo = impl PartialEq<(Foo, i32)>;
 struct Bar;
 
 impl PartialEq<(Foo, i32)> for Bar {
-//~^ ERROR cannot implement trait on type alias impl trait
     fn eq(&self, _other: &(Foo, i32)) -> bool {
         true
     }
 }
 
 fn foo() -> Foo {
+    //~^ ERROR can't compare `Bar` with `(Bar, i32)`
     Bar
 }
 
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr
index 2ef1697ba34..7b63a3d0b9f 100644
--- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr
@@ -1,14 +1,15 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:7:17
+error[E0277]: can't compare `Bar` with `(Bar, i32)`
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:13:13
    |
-LL | impl PartialEq<(Foo, i32)> for Bar {
-   |                 ^^^
+LL | fn foo() -> Foo {
+   |             ^^^ no implementation for `Bar == (Bar, i32)`
+LL |
+LL |     Bar
+   |     --- return type was inferred to be `Bar` here
    |
-note: type alias impl trait defined here
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:3:12
-   |
-LL | type Foo = impl PartialEq<(Foo, i32)>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: the trait `PartialEq<(Bar, i32)>` is not implemented for `Bar`
+   = help: the trait `PartialEq<(Foo, i32)>` is implemented for `Bar`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
index df7966f00e1..91f1ed48133 100644
--- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
@@ -2,11 +2,13 @@
 
 mod a {
     type Foo = impl PartialEq<(Foo, i32)>;
+    //~^ ERROR: unconstrained opaque type
 
     struct Bar;
 
     impl PartialEq<(Bar, i32)> for Bar {
         fn eq(&self, _other: &(Foo, i32)) -> bool {
+            //~^ ERROR: `eq` has an incompatible type for trait
             true
         }
     }
@@ -14,12 +16,13 @@ mod a {
 
 mod b {
     type Foo = impl PartialEq<(Foo, i32)>;
+    //~^ ERROR: unconstrained opaque type
 
     struct Bar;
 
     impl PartialEq<(Foo, i32)> for Bar {
-        //~^ ERROR cannot implement trait on type alias impl trait
         fn eq(&self, _other: &(Bar, i32)) -> bool {
+            //~^ ERROR: `eq` has an incompatible type for trait
             true
         }
     }
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
index 6cd63dcf81c..3dda5761ada 100644
--- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
@@ -1,14 +1,49 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:20:21
+error: unconstrained opaque type
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16
    |
-LL |     impl PartialEq<(Foo, i32)> for Bar {
-   |                     ^^^
+LL |     type Foo = impl PartialEq<(Foo, i32)>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
+
+error[E0053]: method `eq` has an incompatible type for trait
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:30
+   |
+LL |     type Foo = impl PartialEq<(Foo, i32)>;
+   |                -------------------------- the found opaque type
+...
+LL |         fn eq(&self, _other: &(Foo, i32)) -> bool {
+   |                              ^^^^^^^^^^^
+   |                              |
+   |                              expected struct `a::Bar`, found opaque type
+   |                              help: change the parameter type to match the trait: `&(a::Bar, i32)`
    |
-note: type alias impl trait defined here
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:16:16
+   = note: expected fn pointer `fn(&a::Bar, &(a::Bar, i32)) -> _`
+              found fn pointer `fn(&a::Bar, &(a::Foo, i32)) -> _`
+
+error: unconstrained opaque type
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16
    |
 LL |     type Foo = impl PartialEq<(Foo, i32)>;
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
+
+error[E0053]: method `eq` has an incompatible type for trait
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:30
+   |
+LL |     type Foo = impl PartialEq<(Foo, i32)>;
+   |                -------------------------- the expected opaque type
+...
+LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
+   |                              ^^^^^^^^^^^
+   |                              |
+   |                              expected opaque type, found struct `b::Bar`
+   |                              help: change the parameter type to match the trait: `&(b::Foo, i32)`
+   |
+   = note: expected fn pointer `fn(&b::Bar, &(b::Foo, i32)) -> _`
+              found fn pointer `fn(&b::Bar, &(b::Bar, i32)) -> _`
 
-error: aborting due to previous error
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/issues/issue-19086.rs b/src/test/ui/issues/issue-19086.rs
index cc83874cb16..42148c5f5a1 100644
--- a/src/test/ui/issues/issue-19086.rs
+++ b/src/test/ui/issues/issue-19086.rs
@@ -8,6 +8,6 @@ fn main() {
     let f = FooB { x: 3, y: 4 };
     match f {
         FooB(a, b) => println!("{} {}", a, b),
-        //~^ ERROR expected tuple struct or tuple variant, found struct variant `FooB`
+        //~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
     }
 }
diff --git a/src/test/ui/issues/issue-19086.stderr b/src/test/ui/issues/issue-19086.stderr
index a54f1008e4b..a3c06a72511 100644
--- a/src/test/ui/issues/issue-19086.stderr
+++ b/src/test/ui/issues/issue-19086.stderr
@@ -1,4 +1,4 @@
-error[E0532]: expected tuple struct or tuple variant, found struct variant `FooB`
+error[E0532]: expected tuple struct or tuple variant, found variant `FooB`
   --> $DIR/issue-19086.rs:10:9
    |
 LL |     FooB { x: i32, y: i32 }
diff --git a/src/test/ui/issues/issue-23122-2.rs b/src/test/ui/issues/issue-23122-2.rs
index 95e1f60d8b0..338789c2e87 100644
--- a/src/test/ui/issues/issue-23122-2.rs
+++ b/src/test/ui/issues/issue-23122-2.rs
@@ -1,3 +1,4 @@
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
 trait Next {
     type Next: Next;
 }
diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr
index f6cda3de5c7..5828e027b59 100644
--- a/src/test/ui/issues/issue-23122-2.stderr
+++ b/src/test/ui/issues/issue-23122-2.stderr
@@ -1,10 +1,16 @@
-error[E0275]: overflow evaluating the requirement `<T as Next>::Next`
-  --> $DIR/issue-23122-2.rs:10:17
+error[E0275]: overflow evaluating the requirement `<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized`
+  --> $DIR/issue-23122-2.rs:11:17
    |
 LL |     type Next = <GetNext<T::Next> as Next>::Next;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`)
+note: required for `GetNext<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
+  --> $DIR/issue-23122-2.rs:10:15
+   |
+LL | impl<T: Next> Next for GetNext<T> {
+   |               ^^^^     ^^^^^^^^^^
+   = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-23122-2/issue-23122-2.long-type-hash.txt'
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-28992-empty.stderr b/src/test/ui/issues/issue-28992-empty.stderr
index 71f337278f2..f69773b8c2b 100644
--- a/src/test/ui/issues/issue-28992-empty.stderr
+++ b/src/test/ui/issues/issue-28992-empty.stderr
@@ -8,7 +8,7 @@ error[E0164]: expected tuple struct or tuple variant, found associated constant
   --> $DIR/issue-28992-empty.rs:14:12
    |
 LL |     if let S::C2(..) = 0 {}
-   |            ^^^^^^^^^ not a tuple variant or struct
+   |            ^^^^^^^^^ not a tuple struct or tuple variant
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-29723.stderr b/src/test/ui/issues/issue-29723.stderr
index e39ddfc81c9..92ee5cf22b7 100644
--- a/src/test/ui/issues/issue-29723.stderr
+++ b/src/test/ui/issues/issue-29723.stderr
@@ -9,6 +9,11 @@ LL |         0 if { drop(s); false } => String::from("oops"),
 ...
 LL |             s
    |             ^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         0 if { drop(s.clone()); false } => String::from("oops"),
+   |                      ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-42796.stderr b/src/test/ui/issues/issue-42796.stderr
index f3e0e7b20a1..f2971df5db2 100644
--- a/src/test/ui/issues/issue-42796.stderr
+++ b/src/test/ui/issues/issue-42796.stderr
@@ -10,6 +10,10 @@ LL |     println!("{}", s);
    |                    ^ value borrowed here after move
    |
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let mut s_copy = s.clone();
+   |                       ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-56835.stderr b/src/test/ui/issues/issue-56835.stderr
index c200ba8d52a..e949ae7b324 100644
--- a/src/test/ui/issues/issue-56835.stderr
+++ b/src/test/ui/issues/issue-56835.stderr
@@ -8,7 +8,7 @@ error[E0164]: expected tuple struct or tuple variant, found self constructor `Se
   --> $DIR/issue-56835.rs:4:12
    |
 LL |     fn bar(Self(foo): Self) {}
-   |            ^^^^^^^^^ not a tuple variant or struct
+   |            ^^^^^^^^^ not a tuple struct or tuple variant
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-63983.stderr b/src/test/ui/issues/issue-63983.stderr
index eb042834102..f90c8111626 100644
--- a/src/test/ui/issues/issue-63983.stderr
+++ b/src/test/ui/issues/issue-63983.stderr
@@ -7,15 +7,13 @@ LL |     Tuple(i32),
 LL |         MyEnum::Tuple => "",
    |         ^^^^^^^^^^^^^ help: use the tuple variant pattern syntax instead: `MyEnum::Tuple(_)`
 
-error[E0532]: expected unit struct, unit variant or constant, found struct variant `MyEnum::Struct`
+error[E0533]: expected unit struct, unit variant or constant, found struct variant `MyEnum::Struct`
   --> $DIR/issue-63983.rs:10:9
    |
-LL |     Struct{ s: i32 },
-   |     ---------------- `MyEnum::Struct` defined here
-...
 LL |         MyEnum::Struct => "",
-   |         ^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `MyEnum::Struct { s }`
+   |         ^^^^^^^^^^^^^^ not a unit struct, unit variant or constant
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0532`.
+Some errors have detailed explanations: E0532, E0533.
+For more information about an error, try `rustc --explain E0532`.
diff --git a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
index bfabe2d12f7..20d4c418e87 100644
--- a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
+++ b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
@@ -370,23 +370,23 @@ error: layout_of(NicheFirst) = Layout {
                pref: $PREF_ALIGN,
            },
            abi: ScalarPair(
-               Initialized {
+               Union {
                    value: Int(
                        I8,
                        false,
                    ),
-                   valid_range: 0..=4,
                },
-               Union {
+               Initialized {
                    value: Int(
                        I8,
                        false,
                    ),
+                   valid_range: 0..=4,
                },
            ),
            fields: Arbitrary {
                offsets: [
-                   Size(0 bytes),
+                   Size(1 bytes),
                ],
                memory_index: [
                    0,
@@ -394,7 +394,7 @@ error: layout_of(NicheFirst) = Layout {
            },
            largest_niche: Some(
                Niche {
-                   offset: Size(0 bytes),
+                   offset: Size(1 bytes),
                    value: Int(
                        I8,
                        false,
@@ -429,29 +429,29 @@ error: layout_of(NicheFirst) = Layout {
                                    I8,
                                    false,
                                ),
-                               valid_range: 0..=2,
+                               valid_range: 0..=255,
                            },
                            Initialized {
                                value: Int(
                                    I8,
                                    false,
                                ),
-                               valid_range: 0..=255,
+                               valid_range: 0..=2,
                            },
                        ),
                        fields: Arbitrary {
                            offsets: [
-                               Size(0 bytes),
                                Size(1 bytes),
+                               Size(0 bytes),
                            ],
                            memory_index: [
-                               0,
                                1,
+                               0,
                            ],
                        },
                        largest_niche: Some(
                            Niche {
-                               offset: Size(0 bytes),
+                               offset: Size(1 bytes),
                                value: Int(
                                    I8,
                                    false,
diff --git a/src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs b/src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs
index 10f6bd74031..f02a93ed41b 100644
--- a/src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs
+++ b/src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(gen_future, generator_trait, negative_impls)]
+#![feature(generator_trait, negative_impls)]
 
 use std::ops::{Generator, GeneratorState};
 use std::task::{Poll, Context};
diff --git a/src/test/ui/lint/unused/issue-104397.rs b/src/test/ui/lint/unused/issue-104397.rs
new file mode 100644
index 00000000000..94e15cd96bc
--- /dev/null
+++ b/src/test/ui/lint/unused/issue-104397.rs
@@ -0,0 +1,18 @@
+// check-pass
+
+#![warn(unused)]
+#![deny(warnings)]
+
+struct Inv<'a>(&'a mut &'a ());
+
+trait Trait {}
+impl Trait for for<'a> fn(Inv<'a>) {}
+
+fn with_bound()
+where
+    (for<'a> fn(Inv<'a>)): Trait,
+{}
+
+fn main() {
+    with_bound();
+}
diff --git a/src/test/ui/lint/unused/must-use-ops.rs b/src/test/ui/lint/unused/must-use-ops.rs
index 3e425727e78..60f877aa8b3 100644
--- a/src/test/ui/lint/unused/must-use-ops.rs
+++ b/src/test/ui/lint/unused/must-use-ops.rs
@@ -3,12 +3,18 @@
 // check-pass
 
 #![warn(unused_must_use)]
+#![feature(never_type)]
+
+fn deref_never(x: &!) {
+    // Don't lint for uninhabited typess
+    *x;
+}
 
 fn main() {
     let val = 1;
     let val_pointer = &val;
 
-// Comparison Operators
+    // Comparison Operators
     val == 1; //~ WARNING unused comparison
     val < 1; //~ WARNING unused comparison
     val <= 1; //~ WARNING unused comparison
@@ -16,26 +22,30 @@ fn main() {
     val >= 1; //~ WARNING unused comparison
     val > 1; //~ WARNING unused comparison
 
-// Arithmetic Operators
+    // Arithmetic Operators
     val + 2; //~ WARNING unused arithmetic operation
     val - 2; //~ WARNING unused arithmetic operation
     val / 2; //~ WARNING unused arithmetic operation
     val * 2; //~ WARNING unused arithmetic operation
     val % 2; //~ WARNING unused arithmetic operation
 
-// Logical Operators
+    // Logical Operators
     true && true; //~ WARNING unused logical operation
     false || true; //~ WARNING unused logical operation
 
-// Bitwise Operators
+    // Bitwise Operators
     5 ^ val; //~ WARNING unused bitwise operation
     5 & val; //~ WARNING unused bitwise operation
     5 | val; //~ WARNING unused bitwise operation
     5 << val; //~ WARNING unused bitwise operation
     5 >> val; //~ WARNING unused bitwise operation
 
-// Unary Operators
+    // Unary Operators
     !val; //~ WARNING unused unary operation
     -val; //~ WARNING unused unary operation
     *val_pointer; //~ WARNING unused unary operation
+
+    if false {
+        deref_never(&panic!());
+    }
 }
diff --git a/src/test/ui/lint/unused/must-use-ops.stderr b/src/test/ui/lint/unused/must-use-ops.stderr
index b248dd0fe15..79a53d39cbf 100644
--- a/src/test/ui/lint/unused/must-use-ops.stderr
+++ b/src/test/ui/lint/unused/must-use-ops.stderr
@@ -1,5 +1,5 @@
 warning: unused comparison that must be used
-  --> $DIR/must-use-ops.rs:12:5
+  --> $DIR/must-use-ops.rs:18:5
    |
 LL |     val == 1;
    |     ^^^^^^^^ the comparison produces a value
@@ -15,7 +15,7 @@ LL |     let _ = val == 1;
    |     +++++++
 
 warning: unused comparison that must be used
-  --> $DIR/must-use-ops.rs:13:5
+  --> $DIR/must-use-ops.rs:19:5
    |
 LL |     val < 1;
    |     ^^^^^^^ the comparison produces a value
@@ -26,7 +26,7 @@ LL |     let _ = val < 1;
    |     +++++++
 
 warning: unused comparison that must be used
-  --> $DIR/must-use-ops.rs:14:5
+  --> $DIR/must-use-ops.rs:20:5
    |
 LL |     val <= 1;
    |     ^^^^^^^^ the comparison produces a value
@@ -37,7 +37,7 @@ LL |     let _ = val <= 1;
    |     +++++++
 
 warning: unused comparison that must be used
-  --> $DIR/must-use-ops.rs:15:5
+  --> $DIR/must-use-ops.rs:21:5
    |
 LL |     val != 1;
    |     ^^^^^^^^ the comparison produces a value
@@ -48,7 +48,7 @@ LL |     let _ = val != 1;
    |     +++++++
 
 warning: unused comparison that must be used
-  --> $DIR/must-use-ops.rs:16:5
+  --> $DIR/must-use-ops.rs:22:5
    |
 LL |     val >= 1;
    |     ^^^^^^^^ the comparison produces a value
@@ -59,7 +59,7 @@ LL |     let _ = val >= 1;
    |     +++++++
 
 warning: unused comparison that must be used
-  --> $DIR/must-use-ops.rs:17:5
+  --> $DIR/must-use-ops.rs:23:5
    |
 LL |     val > 1;
    |     ^^^^^^^ the comparison produces a value
@@ -70,7 +70,7 @@ LL |     let _ = val > 1;
    |     +++++++
 
 warning: unused arithmetic operation that must be used
-  --> $DIR/must-use-ops.rs:20:5
+  --> $DIR/must-use-ops.rs:26:5
    |
 LL |     val + 2;
    |     ^^^^^^^ the arithmetic operation produces a value
@@ -81,7 +81,7 @@ LL |     let _ = val + 2;
    |     +++++++
 
 warning: unused arithmetic operation that must be used
-  --> $DIR/must-use-ops.rs:21:5
+  --> $DIR/must-use-ops.rs:27:5
    |
 LL |     val - 2;
    |     ^^^^^^^ the arithmetic operation produces a value
@@ -92,7 +92,7 @@ LL |     let _ = val - 2;
    |     +++++++
 
 warning: unused arithmetic operation that must be used
-  --> $DIR/must-use-ops.rs:22:5
+  --> $DIR/must-use-ops.rs:28:5
    |
 LL |     val / 2;
    |     ^^^^^^^ the arithmetic operation produces a value
@@ -103,7 +103,7 @@ LL |     let _ = val / 2;
    |     +++++++
 
 warning: unused arithmetic operation that must be used
-  --> $DIR/must-use-ops.rs:23:5
+  --> $DIR/must-use-ops.rs:29:5
    |
 LL |     val * 2;
    |     ^^^^^^^ the arithmetic operation produces a value
@@ -114,7 +114,7 @@ LL |     let _ = val * 2;
    |     +++++++
 
 warning: unused arithmetic operation that must be used
-  --> $DIR/must-use-ops.rs:24:5
+  --> $DIR/must-use-ops.rs:30:5
    |
 LL |     val % 2;
    |     ^^^^^^^ the arithmetic operation produces a value
@@ -125,7 +125,7 @@ LL |     let _ = val % 2;
    |     +++++++
 
 warning: unused logical operation that must be used
-  --> $DIR/must-use-ops.rs:27:5
+  --> $DIR/must-use-ops.rs:33:5
    |
 LL |     true && true;
    |     ^^^^^^^^^^^^ the logical operation produces a value
@@ -136,7 +136,7 @@ LL |     let _ = true && true;
    |     +++++++
 
 warning: unused logical operation that must be used
-  --> $DIR/must-use-ops.rs:28:5
+  --> $DIR/must-use-ops.rs:34:5
    |
 LL |     false || true;
    |     ^^^^^^^^^^^^^ the logical operation produces a value
@@ -147,7 +147,7 @@ LL |     let _ = false || true;
    |     +++++++
 
 warning: unused bitwise operation that must be used
-  --> $DIR/must-use-ops.rs:31:5
+  --> $DIR/must-use-ops.rs:37:5
    |
 LL |     5 ^ val;
    |     ^^^^^^^ the bitwise operation produces a value
@@ -158,7 +158,7 @@ LL |     let _ = 5 ^ val;
    |     +++++++
 
 warning: unused bitwise operation that must be used
-  --> $DIR/must-use-ops.rs:32:5
+  --> $DIR/must-use-ops.rs:38:5
    |
 LL |     5 & val;
    |     ^^^^^^^ the bitwise operation produces a value
@@ -169,7 +169,7 @@ LL |     let _ = 5 & val;
    |     +++++++
 
 warning: unused bitwise operation that must be used
-  --> $DIR/must-use-ops.rs:33:5
+  --> $DIR/must-use-ops.rs:39:5
    |
 LL |     5 | val;
    |     ^^^^^^^ the bitwise operation produces a value
@@ -180,7 +180,7 @@ LL |     let _ = 5 | val;
    |     +++++++
 
 warning: unused bitwise operation that must be used
-  --> $DIR/must-use-ops.rs:34:5
+  --> $DIR/must-use-ops.rs:40:5
    |
 LL |     5 << val;
    |     ^^^^^^^^ the bitwise operation produces a value
@@ -191,7 +191,7 @@ LL |     let _ = 5 << val;
    |     +++++++
 
 warning: unused bitwise operation that must be used
-  --> $DIR/must-use-ops.rs:35:5
+  --> $DIR/must-use-ops.rs:41:5
    |
 LL |     5 >> val;
    |     ^^^^^^^^ the bitwise operation produces a value
@@ -202,7 +202,7 @@ LL |     let _ = 5 >> val;
    |     +++++++
 
 warning: unused unary operation that must be used
-  --> $DIR/must-use-ops.rs:38:5
+  --> $DIR/must-use-ops.rs:44:5
    |
 LL |     !val;
    |     ^^^^ the unary operation produces a value
@@ -213,7 +213,7 @@ LL |     let _ = !val;
    |     +++++++
 
 warning: unused unary operation that must be used
-  --> $DIR/must-use-ops.rs:39:5
+  --> $DIR/must-use-ops.rs:45:5
    |
 LL |     -val;
    |     ^^^^ the unary operation produces a value
@@ -224,7 +224,7 @@ LL |     let _ = -val;
    |     +++++++
 
 warning: unused unary operation that must be used
-  --> $DIR/must-use-ops.rs:40:5
+  --> $DIR/must-use-ops.rs:46:5
    |
 LL |     *val_pointer;
    |     ^^^^^^^^^^^^ the unary operation produces a value
diff --git a/src/test/ui/lint/unused/must_use-array.rs b/src/test/ui/lint/unused/must_use-array.rs
index 97825dd2f6c..b7bae4b0acf 100644
--- a/src/test/ui/lint/unused/must_use-array.rs
+++ b/src/test/ui/lint/unused/must_use-array.rs
@@ -1,6 +1,7 @@
 #![deny(unused_must_use)]
 
 #[must_use]
+#[derive(Clone, Copy)]
 struct S;
 
 struct A;
@@ -34,6 +35,10 @@ fn array_of_arrays_of_arrays() -> [[[S; 1]; 2]; 1] {
     [[[S], [S]]]
 }
 
+fn usize_max() -> [S; usize::MAX] {
+    [S; usize::MAX]
+}
+
 fn main() {
     empty(); // ok
     singleton(); //~ ERROR unused array of `S` that must be used
@@ -44,4 +49,6 @@ fn main() {
     //~^ ERROR unused array of boxed `T` trait objects in tuple element 1 that must be used
     array_of_arrays_of_arrays();
     //~^ ERROR unused array of arrays of arrays of `S` that must be used
+    usize_max();
+    //~^ ERROR unused array of `S` that must be used
 }
diff --git a/src/test/ui/lint/unused/must_use-array.stderr b/src/test/ui/lint/unused/must_use-array.stderr
index bba2b1ba078..61ef2088d30 100644
--- a/src/test/ui/lint/unused/must_use-array.stderr
+++ b/src/test/ui/lint/unused/must_use-array.stderr
@@ -1,5 +1,5 @@
 error: unused array of `S` that must be used
-  --> $DIR/must_use-array.rs:39:5
+  --> $DIR/must_use-array.rs:44:5
    |
 LL |     singleton();
    |     ^^^^^^^^^^^
@@ -11,34 +11,40 @@ LL | #![deny(unused_must_use)]
    |         ^^^^^^^^^^^^^^^
 
 error: unused array of `S` that must be used
-  --> $DIR/must_use-array.rs:40:5
+  --> $DIR/must_use-array.rs:45:5
    |
 LL |     many();
    |     ^^^^^^
 
 error: unused array of `S` in tuple element 0 that must be used
-  --> $DIR/must_use-array.rs:41:6
+  --> $DIR/must_use-array.rs:46:6
    |
 LL |     ([S], 0, ());
    |      ^^^
 
 error: unused array of implementers of `T` that must be used
-  --> $DIR/must_use-array.rs:42:5
+  --> $DIR/must_use-array.rs:47:5
    |
 LL |     array_of_impl_trait();
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: unused array of boxed `T` trait objects in tuple element 1 that must be used
-  --> $DIR/must_use-array.rs:43:5
+  --> $DIR/must_use-array.rs:48:5
    |
 LL |     impl_array();
    |     ^^^^^^^^^^^^
 
 error: unused array of arrays of arrays of `S` that must be used
-  --> $DIR/must_use-array.rs:45:5
+  --> $DIR/must_use-array.rs:50:5
    |
 LL |     array_of_arrays_of_arrays();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error: unused array of `S` that must be used
+  --> $DIR/must_use-array.rs:52:5
+   |
+LL |     usize_max();
+   |     ^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/liveness/liveness-move-call-arg.stderr b/src/test/ui/liveness/liveness-move-call-arg.stderr
index 7c0e916eddc..d14cd6cb4e0 100644
--- a/src/test/ui/liveness/liveness-move-call-arg.stderr
+++ b/src/test/ui/liveness/liveness-move-call-arg.stderr
@@ -3,9 +3,23 @@ error[E0382]: use of moved value: `x`
    |
 LL |     let x: Box<isize> = Box::new(25);
    |         - move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
-...
+LL |
+LL |     loop {
+   |     ---- inside of this loop
 LL |         take(x);
    |              ^ value moved here, in previous iteration of loop
+   |
+note: consider changing this parameter type in function `take` to borrow instead if owning the value isn't necessary
+  --> $DIR/liveness-move-call-arg.rs:1:13
+   |
+LL | fn take(_x: Box<isize>) {}
+   |    ----     ^^^^^^^^^^ this parameter takes ownership of the value
+   |    |
+   |    in this function
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         take(x.clone());
+   |               ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/liveness/liveness-move-in-loop.stderr b/src/test/ui/liveness/liveness-move-in-loop.stderr
index 832d4f8fa03..a060914f178 100644
--- a/src/test/ui/liveness/liveness-move-in-loop.stderr
+++ b/src/test/ui/liveness/liveness-move-in-loop.stderr
@@ -4,8 +4,22 @@ error[E0382]: use of moved value: `y`
 LL |     let y: Box<isize> = 42.into();
    |         - move occurs because `y` has type `Box<isize>`, which does not implement the `Copy` trait
 ...
+LL |     loop {
+   |     ---- inside of this loop
+LL |         println!("{}", y);
+LL |         loop {
+   |         ---- inside of this loop
+LL |             loop {
+   |             ---- inside of this loop
+LL |                 loop {
+   |                 ---- inside of this loop
 LL |                     x = y;
    |                         ^ value moved here, in previous iteration of loop
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |                     x = y.clone();
+   |                          ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/liveness/liveness-move-in-while.stderr b/src/test/ui/liveness/liveness-move-in-while.stderr
index b04a05fe409..4dff7447dd7 100644
--- a/src/test/ui/liveness/liveness-move-in-while.stderr
+++ b/src/test/ui/liveness/liveness-move-in-while.stderr
@@ -24,12 +24,22 @@ error[E0382]: borrow of moved value: `y`
 LL |     let y: Box<isize> = 42.into();
    |         - move occurs because `y` has type `Box<isize>`, which does not implement the `Copy` trait
 ...
+LL |     loop {
+   |     ---- inside of this loop
 LL |         println!("{}", y);
    |                        ^ value borrowed here after move
 LL |         while true { while true { while true { x = y; x.clone(); } } }
-   |                                                    - value moved here, in previous iteration of loop
+   |         ----------   ----------   ----------       - value moved here, in previous iteration of loop
+   |         |            |            |
+   |         |            |            inside of this loop
+   |         |            inside of this loop
+   |         inside of this loop
    |
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         while true { while true { while true { x = y.clone(); x.clone(); } } }
+   |                                                     ++++++++
 
 error: aborting due to previous error; 3 warnings emitted
 
diff --git a/src/test/ui/liveness/liveness-use-after-move.stderr b/src/test/ui/liveness/liveness-use-after-move.stderr
index 218b93c8e4f..3accba197a1 100644
--- a/src/test/ui/liveness/liveness-use-after-move.stderr
+++ b/src/test/ui/liveness/liveness-use-after-move.stderr
@@ -10,6 +10,10 @@ LL |     println!("{}", *x);
    |                    ^^ value borrowed here after move
    |
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let y = x.clone();
+   |              ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/liveness/liveness-use-after-send.stderr b/src/test/ui/liveness/liveness-use-after-send.stderr
index 8edc0463fe5..65d55ca8f70 100644
--- a/src/test/ui/liveness/liveness-use-after-send.stderr
+++ b/src/test/ui/liveness/liveness-use-after-send.stderr
@@ -8,7 +8,16 @@ LL |     send(ch, message);
 LL |     println!("{}", message);
    |                    ^^^^^^^ value borrowed here after move
    |
+note: consider changing this parameter type in function `send` to borrow instead if owning the value isn't necessary
+  --> $DIR/liveness-use-after-send.rs:3:54
+   |
+LL | fn send<T:Send + std::fmt::Debug>(ch: Chan<T>, data: T) {
+   |    ---- in this function                             ^ this parameter takes ownership of the value
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     send(ch, message.clone());
+   |                     ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/methods/method-path-in-pattern.stderr b/src/test/ui/methods/method-path-in-pattern.stderr
index 1d1bdb6b052..63c7abe0e4a 100644
--- a/src/test/ui/methods/method-path-in-pattern.stderr
+++ b/src/test/ui/methods/method-path-in-pattern.stderr
@@ -2,37 +2,37 @@ error[E0533]: expected unit struct, unit variant or constant, found associated f
   --> $DIR/method-path-in-pattern.rs:15:9
    |
 LL |         Foo::bar => {}
-   |         ^^^^^^^^
+   |         ^^^^^^^^ not a unit struct, unit variant or constant
 
 error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
   --> $DIR/method-path-in-pattern.rs:19:9
    |
 LL |         <Foo>::bar => {}
-   |         ^^^^^^^^^^
+   |         ^^^^^^^^^^ not a unit struct, unit variant or constant
 
 error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::trait_bar`
   --> $DIR/method-path-in-pattern.rs:23:9
    |
 LL |         <Foo>::trait_bar => {}
-   |         ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^ not a unit struct, unit variant or constant
 
 error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
   --> $DIR/method-path-in-pattern.rs:26:12
    |
 LL |     if let Foo::bar = 0u32 {}
-   |            ^^^^^^^^
+   |            ^^^^^^^^ not a unit struct, unit variant or constant
 
 error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
   --> $DIR/method-path-in-pattern.rs:28:12
    |
 LL |     if let <Foo>::bar = 0u32 {}
-   |            ^^^^^^^^^^
+   |            ^^^^^^^^^^ not a unit struct, unit variant or constant
 
 error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::trait_bar`
   --> $DIR/method-path-in-pattern.rs:30:12
    |
 LL |     if let Foo::trait_bar = 0u32 {}
-   |            ^^^^^^^^^^^^^^
+   |            ^^^^^^^^^^^^^^ not a unit struct, unit variant or constant
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.rs b/src/test/ui/mismatched_types/overloaded-calls-bad.rs
index 902a6ec81d6..232cd2ba88c 100644
--- a/src/test/ui/mismatched_types/overloaded-calls-bad.rs
+++ b/src/test/ui/mismatched_types/overloaded-calls-bad.rs
@@ -20,14 +20,23 @@ impl FnOnce<(isize,)> for S {
     }
 }
 
+struct F;
+
+impl FnOnce<(i32,)> for F {
+    type Output = ();
+
+    extern "rust-call" fn call_once(self, args: (i32,)) -> Self::Output {}
+}
+
 fn main() {
-    let mut s = S {
-        x: 3,
-        y: 3,
-    };
-    let ans = s("what");    //~ ERROR mismatched types
+    let mut s = S { x: 3, y: 3 };
+    let ans = s("what");
+    //~^ ERROR mismatched types
     let ans = s();
     //~^ ERROR this function takes 1 argument but 0 arguments were supplied
     let ans = s("burma", "shave");
     //~^ ERROR this function takes 1 argument but 2 arguments were supplied
+
+    F("");
+    //~^ ERROR mismatched types
 }
diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
index fb3597aa853..3a895acbdb5 100644
--- a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
+++ b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/overloaded-calls-bad.rs:28:17
+  --> $DIR/overloaded-calls-bad.rs:33:17
    |
 LL |     let ans = s("what");
    |               - ^^^^^^ expected `isize`, found `&str`
@@ -13,7 +13,7 @@ LL | impl FnMut<(isize,)> for S {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0057]: this function takes 1 argument but 0 arguments were supplied
-  --> $DIR/overloaded-calls-bad.rs:29:15
+  --> $DIR/overloaded-calls-bad.rs:35:15
    |
 LL |     let ans = s();
    |               ^-- an argument of type `isize` is missing
@@ -29,7 +29,7 @@ LL |     let ans = s(/* isize */);
    |                ~~~~~~~~~~~~~
 
 error[E0057]: this function takes 1 argument but 2 arguments were supplied
-  --> $DIR/overloaded-calls-bad.rs:31:15
+  --> $DIR/overloaded-calls-bad.rs:37:15
    |
 LL |     let ans = s("burma", "shave");
    |               ^ -------  ------- argument of type `&'static str` unexpected
@@ -46,7 +46,21 @@ help: remove the extra argument
 LL |     let ans = s(/* isize */);
    |                ~~~~~~~~~~~~~
 
-error: aborting due to 3 previous errors
+error[E0308]: mismatched types
+  --> $DIR/overloaded-calls-bad.rs:40:7
+   |
+LL |     F("");
+   |     - ^^ expected `i32`, found `&str`
+   |     |
+   |     arguments to this struct are incorrect
+   |
+note: implementation defined here
+  --> $DIR/overloaded-calls-bad.rs:25:1
+   |
+LL | impl FnOnce<(i32,)> for F {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0057, E0308.
 For more information about an error, try `rustc --explain E0057`.
diff --git a/src/test/ui/moves/borrow-closures-instead-of-move.stderr b/src/test/ui/moves/borrow-closures-instead-of-move.stderr
index 3146b695900..9a84ddef7e6 100644
--- a/src/test/ui/moves/borrow-closures-instead-of-move.stderr
+++ b/src/test/ui/moves/borrow-closures-instead-of-move.stderr
@@ -4,9 +4,17 @@ error[E0382]: use of moved value: `f`
 LL | fn takes_fn(f: impl Fn()) {
    |             - move occurs because `f` has type `impl Fn()`, which does not implement the `Copy` trait
 LL |     loop {
+   |     ---- inside of this loop
 LL |         takes_fnonce(f);
    |                      ^ value moved here, in previous iteration of loop
    |
+note: consider changing this parameter type in function `takes_fnonce` to borrow instead if owning the value isn't necessary
+  --> $DIR/borrow-closures-instead-of-move.rs:34:20
+   |
+LL | fn takes_fnonce(_: impl FnOnce()) {}
+   |    ------------    ^^^^^^^^^^^^^ this parameter takes ownership of the value
+   |    |
+   |    in this function
 help: consider borrowing `f`
    |
 LL |         takes_fnonce(&f);
@@ -24,6 +32,13 @@ LL |         takes_fnonce(m);
 LL |     takes_fnonce(m);
    |                  ^ value used here after move
    |
+note: consider changing this parameter type in function `takes_fnonce` to borrow instead if owning the value isn't necessary
+  --> $DIR/borrow-closures-instead-of-move.rs:34:20
+   |
+LL | fn takes_fnonce(_: impl FnOnce()) {}
+   |    ------------    ^^^^^^^^^^^^^ this parameter takes ownership of the value
+   |    |
+   |    in this function
 help: consider mutably borrowing `m`
    |
 LL |         takes_fnonce(&mut m);
diff --git a/src/test/ui/moves/issue-46099-move-in-macro.stderr b/src/test/ui/moves/issue-46099-move-in-macro.stderr
index baa87e3e9fd..94bc9e6f454 100644
--- a/src/test/ui/moves/issue-46099-move-in-macro.stderr
+++ b/src/test/ui/moves/issue-46099-move-in-macro.stderr
@@ -5,6 +5,11 @@ LL |     let b = Box::new(true);
    |         - move occurs because `b` has type `Box<bool>`, which does not implement the `Copy` trait
 LL |     test!({b});
    |            ^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     test!({b.clone()});
+   |             ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/moves/issue-72649-uninit-in-loop.rs b/src/test/ui/moves/issue-72649-uninit-in-loop.rs
index d76b69ecdc8..56c225bab8c 100644
--- a/src/test/ui/moves/issue-72649-uninit-in-loop.rs
+++ b/src/test/ui/moves/issue-72649-uninit-in-loop.rs
@@ -25,7 +25,7 @@ fn moved_here_1() {
 fn moved_here_2() {
     let value = NonCopy{};
     //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
-    loop {
+    loop { //~ NOTE inside of this loop
         let _used = value;
         //~^ NOTE value moved here
         loop {
@@ -38,7 +38,7 @@ fn moved_here_2() {
 fn moved_loop_1() {
     let value = NonCopy{};
     //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
-    loop {
+    loop { //~ NOTE inside of this loop
         let _used = value; //~ ERROR use of moved value: `value`
         //~^ NOTE value moved here, in previous iteration of loop
     }
@@ -49,7 +49,7 @@ fn moved_loop_2() {
     //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
     let _used = value;
     value = NonCopy{};
-    loop {
+    loop { //~ NOTE inside of this loop
         let _used2 = value; //~ ERROR use of moved value: `value`
         //~^ NOTE value moved here, in previous iteration of loop
     }
diff --git a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr
index 974994223a3..7e119fe8cda 100644
--- a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr
+++ b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr
@@ -15,7 +15,9 @@ error[E0382]: use of moved value: `value`
    |
 LL |     let value = NonCopy{};
    |         ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
-...
+LL |
+LL |     loop {
+   |     ---- inside of this loop
 LL |         let _used = value;
    |                     ----- value moved here
 ...
@@ -27,7 +29,9 @@ error[E0382]: use of moved value: `value`
    |
 LL |     let value = NonCopy{};
    |         ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
-...
+LL |
+LL |     loop {
+   |     ---- inside of this loop
 LL |         let _used = value;
    |                     ^^^^^ value moved here, in previous iteration of loop
 
@@ -37,6 +41,8 @@ error[E0382]: use of moved value: `value`
 LL |     let mut value = NonCopy{};
    |         --------- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
 ...
+LL |     loop {
+   |     ---- inside of this loop
 LL |         let _used2 = value;
    |                      ^^^^^ value moved here, in previous iteration of loop
 
diff --git a/src/test/ui/moves/move-fn-self-receiver.stderr b/src/test/ui/moves/move-fn-self-receiver.stderr
index 3a686121a92..c13dc58826e 100644
--- a/src/test/ui/moves/move-fn-self-receiver.stderr
+++ b/src/test/ui/moves/move-fn-self-receiver.stderr
@@ -96,6 +96,10 @@ note: this function takes ownership of the receiver `self`, which moves `rc_foo`
    |
 LL |     fn use_rc_self(self: Rc<Self>) {}
    |                    ^^^^
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     rc_foo.clone().use_rc_self();
+   |           ++++++++
 
 error[E0382]: use of moved value: `foo_add`
   --> $DIR/move-fn-self-receiver.rs:59:5
@@ -137,6 +141,11 @@ LL |     for _val in explicit_into_iter.into_iter() {}
    |                                    ----------- `explicit_into_iter` moved due to this method call
 LL |     explicit_into_iter;
    |     ^^^^^^^^^^^^^^^^^^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     for _val in explicit_into_iter.clone().into_iter() {}
+   |                                   ++++++++
 
 error[E0382]: use of moved value: `container`
   --> $DIR/move-fn-self-receiver.rs:71:5
@@ -160,6 +169,7 @@ error[E0382]: use of moved value: `foo2`
 LL |     let foo2 = Foo;
    |         ---- move occurs because `foo2` has type `Foo`, which does not implement the `Copy` trait
 LL |     loop {
+   |     ---- inside of this loop
 LL |         foo2.use_self();
    |         ^^^^ ---------- `foo2` moved due to this method call, in previous iteration of loop
 
diff --git a/src/test/ui/moves/move-guard-same-consts.stderr b/src/test/ui/moves/move-guard-same-consts.stderr
index 2048fefefa3..86e5f65248b 100644
--- a/src/test/ui/moves/move-guard-same-consts.stderr
+++ b/src/test/ui/moves/move-guard-same-consts.stderr
@@ -8,6 +8,18 @@ LL |         (1, 2) if take(x) => (),
    |                        - value moved here
 LL |         (1, 2) if take(x) => (),
    |                        ^ value used here after move
+   |
+note: consider changing this parameter type in function `take` to borrow instead if owning the value isn't necessary
+  --> $DIR/move-guard-same-consts.rs:25:15
+   |
+LL | fn take<T>(_: T) -> bool { false }
+   |    ----       ^ this parameter takes ownership of the value
+   |    |
+   |    in this function
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         (1, 2) if take(x.clone()) => (),
+   |                         ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/moves/move-in-guard-1.stderr b/src/test/ui/moves/move-in-guard-1.stderr
index 5e9aa66b90d..f04cb34d7c4 100644
--- a/src/test/ui/moves/move-in-guard-1.stderr
+++ b/src/test/ui/moves/move-in-guard-1.stderr
@@ -8,6 +8,18 @@ LL |         (1, _) if take(x) => (),
    |                        - value moved here
 LL |         (_, 2) if take(x) => (),
    |                        ^ value used here after move
+   |
+note: consider changing this parameter type in function `take` to borrow instead if owning the value isn't necessary
+  --> $DIR/move-in-guard-1.rs:15:15
+   |
+LL | fn take<T>(_: T) -> bool { false }
+   |    ----       ^ this parameter takes ownership of the value
+   |    |
+   |    in this function
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         (1, _) if take(x.clone()) => (),
+   |                         ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/moves/move-in-guard-2.stderr b/src/test/ui/moves/move-in-guard-2.stderr
index 8d636c11b78..26047861f55 100644
--- a/src/test/ui/moves/move-in-guard-2.stderr
+++ b/src/test/ui/moves/move-in-guard-2.stderr
@@ -6,6 +6,18 @@ LL |     let x: Box<_> = Box::new(1);
 ...
 LL |         (_, 2) if take(x) => (),
    |                        ^ value used here after move
+   |
+note: consider changing this parameter type in function `take` to borrow instead if owning the value isn't necessary
+  --> $DIR/move-in-guard-2.rs:13:15
+   |
+LL | fn take<T>(_: T) -> bool { false }
+   |    ----       ^ this parameter takes ownership of the value
+   |    |
+   |    in this function
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         (_, 2) if take(x.clone()) => (),
+   |                         ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
index 3cc8ca29144..a49ee31b466 100644
--- a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
+++ b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
@@ -13,6 +13,10 @@ note: this function takes ownership of the receiver `self`, which moves `x`
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
    |                  ^^^^
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     consume(x.clone().into_iter().next().unwrap());
+   |              ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr b/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr
index a315bbaab33..db4382b58fc 100644
--- a/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr
+++ b/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr
@@ -8,7 +8,7 @@ LL |     consume(node) + r
    |             ^^^^ value used here after partial move
    |
    = note: partial move occurs because value has type `Box<List>`, which does not implement the `Copy` trait
-help: borrow this field in the pattern to avoid moving `node.next.0`
+help: borrow this binding in the pattern to avoid moving the value
    |
 LL |         Some(ref right) => consume(right),
    |              +++
diff --git a/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr b/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr
index ee7971691a4..0930df14805 100644
--- a/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr
+++ b/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr
@@ -9,6 +9,11 @@ LL |     let _y = Foo { f:x };
 LL |
 LL |     touch(&x);
    |           ^^ value borrowed here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _y = Foo { f:x.clone() };
+   |                       ++++++++
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-distribute-copy-over-paren.rs:21:11
@@ -21,6 +26,11 @@ LL |     let _y = Foo { f:(((x))) };
 LL |
 LL |     touch(&x);
    |           ^^ value borrowed here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _y = Foo { f:(((x))).clone() };
+   |                             ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/moves/moves-based-on-type-exprs.stderr b/src/test/ui/moves/moves-based-on-type-exprs.stderr
index 9bcec36740d..838b1282cb4 100644
--- a/src/test/ui/moves/moves-based-on-type-exprs.stderr
+++ b/src/test/ui/moves/moves-based-on-type-exprs.stderr
@@ -7,6 +7,11 @@ LL |     let _y = Foo { f:x };
    |                      - value moved here
 LL |     touch(&x);
    |           ^^ value borrowed here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _y = Foo { f:x.clone() };
+   |                       ++++++++
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:18:11
@@ -17,6 +22,11 @@ LL |     let _y = (x, 3);
    |               - value moved here
 LL |     touch(&x);
    |           ^^ value borrowed here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _y = (x.clone(), 3);
+   |                ++++++++
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:35:11
@@ -29,6 +39,11 @@ LL |         x
 ...
 LL |     touch(&x);
    |           ^^ value borrowed here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         x.clone()
+   |          ++++++++
 
 error[E0382]: borrow of moved value: `y`
   --> $DIR/moves-based-on-type-exprs.rs:36:11
@@ -41,6 +56,11 @@ LL |         y
 ...
 LL |     touch(&y);
    |           ^^ value borrowed here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         y.clone()
+   |          ++++++++
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:46:11
@@ -53,6 +73,11 @@ LL |         true => x,
 ...
 LL |     touch(&x);
    |           ^^ value borrowed here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         true => x.clone(),
+   |                  ++++++++
 
 error[E0382]: borrow of moved value: `y`
   --> $DIR/moves-based-on-type-exprs.rs:47:11
@@ -65,6 +90,11 @@ LL |         false => y
 ...
 LL |     touch(&y);
    |           ^^ value borrowed here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         false => y.clone()
+   |                   ++++++++
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:58:11
@@ -77,6 +107,18 @@ LL |         _ if guard(x) => 10,
 ...
 LL |     touch(&x);
    |           ^^ value borrowed here after move
+   |
+note: consider changing this parameter type in function `guard` to borrow instead if owning the value isn't necessary
+  --> $DIR/moves-based-on-type-exprs.rs:6:14
+   |
+LL | fn guard(_s: String) -> bool {panic!()}
+   |    -----     ^^^^^^ this parameter takes ownership of the value
+   |    |
+   |    in this function
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         _ if guard(x.clone()) => 10,
+   |                     ++++++++
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:65:11
@@ -87,6 +129,11 @@ LL |     let _y = [x];
    |               - value moved here
 LL |     touch(&x);
    |           ^^ value borrowed here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _y = [x.clone()];
+   |                ++++++++
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:71:11
@@ -97,6 +144,11 @@ LL |     let _y = vec![x];
    |                   - value moved here
 LL |     touch(&x);
    |           ^^ value borrowed here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _y = vec![x.clone()];
+   |                    ++++++++
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:77:11
@@ -113,6 +165,10 @@ note: this function takes ownership of the receiver `self`, which moves `x`
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
    |                  ^^^^
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _y = x.clone().into_iter().next().unwrap();
+   |               ++++++++
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:83:11
@@ -129,6 +185,10 @@ note: this function takes ownership of the receiver `self`, which moves `x`
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
    |                  ^^^^
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _y = [x.clone().into_iter().next().unwrap(); 1];
+   |                ++++++++
 
 error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/moves/moves-based-on-type-match-bindings.stderr b/src/test/ui/moves/moves-based-on-type-match-bindings.stderr
index ad1a2db8b52..225935532ea 100644
--- a/src/test/ui/moves/moves-based-on-type-match-bindings.stderr
+++ b/src/test/ui/moves/moves-based-on-type-match-bindings.stderr
@@ -8,6 +8,10 @@ LL |     touch(&x);
    |           ^^ value borrowed here after partial move
    |
    = note: partial move occurs because `x.f` has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         Foo {ref f} => {}
+   |              +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/moves/moves-based-on-type-tuple.stderr b/src/test/ui/moves/moves-based-on-type-tuple.stderr
index eef8ce61fa9..0bcce301263 100644
--- a/src/test/ui/moves/moves-based-on-type-tuple.stderr
+++ b/src/test/ui/moves/moves-based-on-type-tuple.stderr
@@ -8,6 +8,11 @@ LL |     Box::new((x, x))
    |               -  ^ value used here after move
    |               |
    |               value moved here
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     Box::new((x.clone(), x))
+   |                ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr b/src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr
index c25981e6f80..22e7951dbe3 100644
--- a/src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr
+++ b/src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr
@@ -7,6 +7,11 @@ LL |     (t, t)
    |      -  ^ value used here after move
    |      |
    |      value moved here
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     (t.clone(), t)
+   |       ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/namespace/namespace-mix.rs b/src/test/ui/namespace/namespace-mix.rs
index b0f7e3c6225..c5b30f148bd 100644
--- a/src/test/ui/namespace/namespace-mix.rs
+++ b/src/test/ui/namespace/namespace-mix.rs
@@ -97,13 +97,13 @@ mod m8 {
 
 fn f78() {
     check(m7::V{}); //~ ERROR c::Item
-    check(m7::V); //~ ERROR expected value, found struct variant `m7::V`
+    check(m7::V); //~ ERROR expected value, found type alias `m7::V`
     check(m8::V{}); //~ ERROR c::E
     check(m8::V); //~ ERROR c::Item
 }
 fn xf78() {
     check(xm7::V{}); //~ ERROR c::Item
-    check(xm7::V); //~ ERROR expected value, found struct variant `xm7::V`
+    check(xm7::V); //~ ERROR expected value, found type alias `xm7::V`
     check(xm8::V{}); //~ ERROR c::E
     check(xm8::V); //~ ERROR c::Item
 }
diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr
index c07914df727..cb72d4a1c42 100644
--- a/src/test/ui/namespace/namespace-mix.stderr
+++ b/src/test/ui/namespace/namespace-mix.stderr
@@ -52,21 +52,16 @@ LL -     check(xm1::S);
 LL +     check(S);
    |
 
-error[E0423]: expected value, found struct variant `m7::V`
+error[E0423]: expected value, found type alias `m7::V`
   --> $DIR/namespace-mix.rs:100:11
    |
-LL |         V {},
-   |         ---- `m7::V` defined here
 LL |         TV(),
    |         ---- similarly named tuple variant `TV` defined here
 ...
 LL |     check(m7::V);
    |           ^^^^^
    |
-help: use struct literal syntax instead
-   |
-LL |     check(m7::V {});
-   |           ~~~~~~~~
+   = note: can't use a type alias as a constructor
 help: a tuple variant with a similar name exists
    |
 LL |     check(m7::TV);
@@ -83,23 +78,18 @@ LL -     check(m7::V);
 LL +     check(V);
    |
 
-error[E0423]: expected value, found struct variant `xm7::V`
+error[E0423]: expected value, found type alias `xm7::V`
   --> $DIR/namespace-mix.rs:106:11
    |
 LL |     check(xm7::V);
    |           ^^^^^^
    |
-  ::: $DIR/auxiliary/namespace-mix.rs:6:9
+  ::: $DIR/auxiliary/namespace-mix.rs:7:9
    |
-LL |         V {},
-   |         - `xm7::V` defined here
 LL |         TV(),
    |         -- similarly named tuple variant `TV` defined here
    |
-help: use struct literal syntax instead
-   |
-LL |     check(xm7::V { /* fields */ });
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   = note: can't use a type alias as a constructor
 help: a tuple variant with a similar name exists
    |
 LL |     check(xm7::TV);
diff --git a/src/test/ui/nll/closure-access-spans.stderr b/src/test/ui/nll/closure-access-spans.stderr
index e9d7ca953d6..0a09353b8ec 100644
--- a/src/test/ui/nll/closure-access-spans.stderr
+++ b/src/test/ui/nll/closure-access-spans.stderr
@@ -67,6 +67,11 @@ LL |     || x.len();
    |     ^^ - borrow occurs due to use in closure
    |     |
    |     value borrowed here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let r = x.clone();
+   |              ++++++++
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/closure-access-spans.rs:40:5
@@ -79,6 +84,11 @@ LL |     || x = String::new();
    |     ^^ - borrow occurs due to use in closure
    |     |
    |     value borrowed here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let r = x.clone();
+   |              ++++++++
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/closure-access-spans.rs:45:5
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
index 947c9e29b45..97ed414b1ec 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
+++ b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
@@ -37,6 +37,11 @@ LL |     let mut t: T = (0, Box::new(0)); drop(t);
    |         move occurs because `t` has type `(u32, Box<u32>)`, which does not implement the `Copy` trait
 LL |     t.0 = 10; t.1 = Box::new(20);
    |     ^^^^^^^^ value partially assigned here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let mut t: T = (0, Box::new(0)); drop(t.clone());
+   |                                            ++++++++
 
 error[E0381]: partially assigned binding `s` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:123:5
@@ -77,6 +82,11 @@ LL |     let mut t: T = (0, Box::new(0)); drop(t);
    |         move occurs because `t` has type `(u32, Box<u32>)`, which does not implement the `Copy` trait
 LL |     t.0 = 10;
    |     ^^^^^^^^ value partially assigned here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let mut t: T = (0, Box::new(0)); drop(t.clone());
+   |                                            ++++++++
 
 error[E0381]: partially assigned binding `s` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:149:5
@@ -208,6 +218,11 @@ LL |         c2 => {
    |         -- value moved here
 LL |             c.0 = 2;
    |             ^^^^^^^ value partially assigned here after move
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref c2 => {
+   |         +++
 
 error[E0382]: assign to part of moved value: `c`
   --> $DIR/issue-21232-partial-init-and-use.rs:255:13
@@ -219,6 +234,11 @@ LL |         c2 => {
    |         -- value moved here
 LL |             (c.1).0 = 2;
    |             ^^^^^^^^^^^ value partially assigned here after move
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref c2 => {
+   |         +++
 
 error[E0382]: assign to part of moved value: `c.1`
   --> $DIR/issue-21232-partial-init-and-use.rs:263:13
@@ -229,6 +249,10 @@ LL |             ((c.1).1).0 = 3;
    |             ^^^^^^^^^^^^^^^ value partially assigned here after move
    |
    = note: move occurs because `c.1` has type `(i32, (i32, String))`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref c2 => {
+   |         +++
 
 error: aborting due to 23 previous errors
 
diff --git a/src/test/ui/nll/issue-51512.stderr b/src/test/ui/nll/issue-51512.stderr
index e591ca08290..072e96788b1 100644
--- a/src/test/ui/nll/issue-51512.stderr
+++ b/src/test/ui/nll/issue-51512.stderr
@@ -7,6 +7,11 @@ LL |     let r = range;
    |             ----- value moved here
 LL |     let x = range.start;
    |             ^^^^^^^^^^^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let r = range.clone();
+   |                  ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/issue-53807.stderr b/src/test/ui/nll/issue-53807.stderr
index 574a114340f..d8f58b59131 100644
--- a/src/test/ui/nll/issue-53807.stderr
+++ b/src/test/ui/nll/issue-53807.stderr
@@ -5,7 +5,7 @@ LL |         if let Some(thing) = maybe {
    |                     ^^^^^ value moved here, in previous iteration of loop
    |
    = note: move occurs because value has type `Vec<bool>`, which does not implement the `Copy` trait
-help: borrow this field in the pattern to avoid moving `maybe.0`
+help: borrow this binding in the pattern to avoid moving the value
    |
 LL |         if let Some(ref thing) = maybe {
    |                     +++
diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr
index 2d48a914218..f72ed3af718 100644
--- a/src/test/ui/nll/match-cfg-fake-edges.stderr
+++ b/src/test/ui/nll/match-cfg-fake-edges.stderr
@@ -26,6 +26,11 @@ LL |         false if { drop(x); true } => 1,
 LL |         true => {
 LL |             x;
    |             ^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         false if { drop(x.clone()); true } => 1,
+   |                          ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/ref-suggestion.stderr b/src/test/ui/nll/ref-suggestion.stderr
index a973c583a9d..b1f5117cb02 100644
--- a/src/test/ui/nll/ref-suggestion.stderr
+++ b/src/test/ui/nll/ref-suggestion.stderr
@@ -7,6 +7,11 @@ LL |     let y = x;
    |             - value moved here
 LL |     x;
    |     ^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let y = x.clone();
+   |              ++++++++
 
 error[E0382]: use of moved value: `x`
   --> $DIR/ref-suggestion.rs:8:5
@@ -17,6 +22,11 @@ LL |     let mut y = x;
    |                 - value moved here
 LL |     x;
    |     ^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let mut y = x.clone();
+   |                  ++++++++
 
 error[E0382]: use of partially moved value: `x`
   --> $DIR/ref-suggestion.rs:16:5
@@ -28,7 +38,7 @@ LL |     x;
    |     ^ value used here after partial move
    |
    = note: partial move occurs because value has type `Vec<i32>`, which does not implement the `Copy` trait
-help: borrow this field in the pattern to avoid moving `x.0.0`
+help: borrow this binding in the pattern to avoid moving the value
    |
 LL |         (Some(ref y), ()) => {},
    |               +++
diff --git a/src/test/ui/parser/issue-104620.rs b/src/test/ui/parser/issue-104620.rs
new file mode 100644
index 00000000000..f49476c4408
--- /dev/null
+++ b/src/test/ui/parser/issue-104620.rs
@@ -0,0 +1,4 @@
+#![feature(rustc_attrs)]
+
+#![rustc_dummy=5z] //~ ERROR unexpected expression: `5z`
+fn main() {}
diff --git a/src/test/ui/parser/issue-104620.stderr b/src/test/ui/parser/issue-104620.stderr
new file mode 100644
index 00000000000..d06a6b2554b
--- /dev/null
+++ b/src/test/ui/parser/issue-104620.stderr
@@ -0,0 +1,8 @@
+error: unexpected expression: `5z`
+  --> $DIR/issue-104620.rs:3:16
+   |
+LL | #![rustc_dummy=5z]
+   |                ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr
index 483312c16cc..04968bbdf99 100644
--- a/src/test/ui/parser/recover-from-bad-variant.stderr
+++ b/src/test/ui/parser/recover-from-bad-variant.stderr
@@ -14,14 +14,11 @@ LL -     let x = Enum::Foo(a: 3, b: 4);
 LL +     let x = Enum::Foo(3, 4);
    |
 
-error[E0532]: expected tuple struct or tuple variant, found struct variant `Enum::Foo`
+error[E0164]: expected tuple struct or tuple variant, found struct variant `Enum::Foo`
   --> $DIR/recover-from-bad-variant.rs:10:9
    |
-LL |     Foo { a: usize, b: usize },
-   |     -------------------------- `Enum::Foo` defined here
-...
 LL |         Enum::Foo(a, b) => {}
-   |         ^^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `Enum::Foo { a, b }`
+   |         ^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
 
 error[E0769]: tuple variant `Enum::Bar` written as struct variant
   --> $DIR/recover-from-bad-variant.rs:12:9
@@ -36,5 +33,5 @@ LL |         Enum::Bar(a, b) => {}
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0532, E0769.
-For more information about an error, try `rustc --explain E0532`.
+Some errors have detailed explanations: E0164, E0769.
+For more information about an error, try `rustc --explain E0164`.
diff --git a/src/test/ui/parser/struct-literal-variant-in-if.stderr b/src/test/ui/parser/struct-literal-variant-in-if.stderr
index 4cffbe433b8..9f0c0074d67 100644
--- a/src/test/ui/parser/struct-literal-variant-in-if.stderr
+++ b/src/test/ui/parser/struct-literal-variant-in-if.stderr
@@ -42,16 +42,11 @@ help: surround the struct literal with parentheses
 LL |     if x == (E::K { field: "" }) {}
    |             +                  +
 
-error[E0423]: expected value, found struct variant `E::V`
+error[E0533]: expected value, found struct variant `E::V`
   --> $DIR/struct-literal-variant-in-if.rs:10:13
    |
 LL |     if x == E::V { field } {}
    |             ^^^^ not a value
-   |
-help: surround the struct literal with parentheses
-   |
-LL |     if x == (E::V { field }) {}
-   |             +              +
 
 error[E0308]: mismatched types
   --> $DIR/struct-literal-variant-in-if.rs:10:20
@@ -72,5 +67,5 @@ LL |     let y: usize = ();
 
 error: aborting due to 7 previous errors
 
-Some errors have detailed explanations: E0308, E0423.
+Some errors have detailed explanations: E0308, E0533.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
index fad84dda0e1..c8b45fd24d9 100644
--- a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
+++ b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
@@ -16,6 +16,11 @@ LL |         Some(_z @ ref _y) => {}
    |              |    value borrowed here after move
    |              value moved into `_z` here
    |              move occurs because `_z` has type `X` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         Some(ref _z @ ref _y) => {}
+   |              +++
 
 error: cannot move out of value because it is borrowed
   --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:26:14
@@ -35,6 +40,11 @@ LL |         Some(_z @ ref mut _y) => {}
    |              |    value borrowed here after move
    |              value moved into `_z` here
    |              move occurs because `_z` has type `X` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         Some(ref _z @ ref mut _y) => {}
+   |              +++
 
 error[E0382]: borrow of moved value
   --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:12:14
@@ -45,7 +55,7 @@ LL |         Some(ref _y @ _z) => {}
    |              value borrowed here after move
    |
    = note: move occurs because value has type `X`, which does not implement the `Copy` trait
-help: borrow this field in the pattern to avoid moving `x.0`
+help: borrow this binding in the pattern to avoid moving the value
    |
 LL |         Some(ref _y @ ref _z) => {}
    |                       +++
@@ -59,7 +69,7 @@ LL |         Some(ref mut _y @ _z) => {}
    |              value borrowed here after move
    |
    = note: move occurs because value has type `X`, which does not implement the `Copy` trait
-help: borrow this field in the pattern to avoid moving `x.0`
+help: borrow this binding in the pattern to avoid moving the value
    |
 LL |         Some(ref mut _y @ ref _z) => {}
    |                           +++
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
index a227cc583d6..32489715112 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
@@ -6,6 +6,11 @@ LL |     let a @ b = U;
    |         |   |
    |         |   value moved here
    |         value used here after move
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ ref b = U;
+   |         +++     +++
 
 error[E0382]: use of partially moved value
   --> $DIR/borrowck-move-and-move.rs:13:9
@@ -16,6 +21,10 @@ LL |     let a @ (b, c) = (U, U);
    |         value used here after partial move
    |
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ (b, ref c) = (U, U);
+   |         +++         +++
 
 error[E0382]: use of partially moved value
   --> $DIR/borrowck-move-and-move.rs:15:9
@@ -26,6 +35,10 @@ LL |     let a @ (b, c) = (u(), u());
    |         value used here after partial move
    |
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ (b, ref c) = (u(), u());
+   |         +++         +++
 
 error[E0382]: use of moved value
   --> $DIR/borrowck-move-and-move.rs:18:16
@@ -36,6 +49,11 @@ LL |         a @ Ok(b) | a @ Err(b) => {}
    |         -      ^ value used here after move
    |         |
    |         value moved here
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref a @ Ok(b) | a @ Err(b) => {}
+   |         +++
 
 error[E0382]: use of moved value
   --> $DIR/borrowck-move-and-move.rs:18:29
@@ -46,6 +64,11 @@ LL |         a @ Ok(b) | a @ Err(b) => {}
    |                     -       ^ value used here after move
    |                     |
    |                     value moved here
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         a @ Ok(b) | ref a @ Err(b) => {}
+   |                     +++
 
 error[E0382]: use of partially moved value
   --> $DIR/borrowck-move-and-move.rs:25:9
@@ -56,6 +79,10 @@ LL |         xs @ [a, .., b] => {}
    |         value used here after partial move
    |
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref xs @ [a, .., ref b] => {}
+   |         +++              +++
 
 error[E0382]: use of partially moved value
   --> $DIR/borrowck-move-and-move.rs:29:9
@@ -66,6 +93,10 @@ LL |         xs @ [_, ys @ .., _] => {}
    |         value used here after partial move
    |
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref xs @ [_, ref ys @ .., _] => {}
+   |         +++          +++
 
 error[E0382]: use of moved value
   --> $DIR/borrowck-move-and-move.rs:22:12
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
index 002c7609f61..f27df32ccfa 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
@@ -79,6 +79,10 @@ LL |     let ref a @ box b = Box::new(NC);
    |         value borrowed here after move
    |
    = note: move occurs because value has type `NC`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ box ref b = Box::new(NC);
+   |                     +++
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-at-and-box.rs:38:9
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr
index be4e81c61aa..d6474f1b49f 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr
@@ -7,6 +7,11 @@ LL |     let a @ ref b = U;
    |         |   value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ ref b = U;
+   |         +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
index a9e66de0842..389e86e6464 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
@@ -7,6 +7,11 @@ LL |     let a @ ref b = U;
    |         |   value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ ref b = U;
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:9
@@ -18,6 +23,11 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |         |            value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ (mut b @ ref mut c, d @ ref e) = (U, U);
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:14
@@ -28,6 +38,11 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |              |       value borrowed here after move
    |              value moved into `b` here
    |              move occurs because `b` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let a @ (ref mut b @ ref mut c, d @ ref e) = (U, U);
+   |              +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:33
@@ -38,6 +53,11 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |                                 |   value borrowed here after move
    |                                 value moved into `d` here
    |                                 move occurs because `d` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let a @ (mut b @ ref mut c, ref d @ ref e) = (U, U);
+   |                                 +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:29:9
@@ -49,6 +69,11 @@ LL |     let a @ [ref mut b, ref c] = [U, U];
    |         |    value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ [ref mut b, ref c] = [U, U];
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:9
@@ -59,6 +84,11 @@ LL |     let a @ ref b = u();
    |         |   value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ ref b = u();
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:9
@@ -70,6 +100,11 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |         |            value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:14
@@ -80,6 +115,11 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |              |       value borrowed here after move
    |              value moved into `b` here
    |              move occurs because `b` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let a @ (ref mut b @ ref mut c, d @ ref e) = (u(), u());
+   |              +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:33
@@ -90,6 +130,11 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |                                 |   value borrowed here after move
    |                                 value moved into `d` here
    |                                 move occurs because `d` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let a @ (mut b @ ref mut c, ref d @ ref e) = (u(), u());
+   |                                 +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:9
@@ -101,6 +146,11 @@ LL |     let a @ [ref mut b, ref c] = [u(), u()];
    |         |    value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ [ref mut b, ref c] = [u(), u()];
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:42:9
@@ -111,6 +161,11 @@ LL |         a @ Some(ref b) => {}
    |         |        value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref a @ Some(ref b) => {}
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:9
@@ -122,6 +177,11 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         |                 value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref a @ Some((mut b @ ref mut c, d @ ref e)) => {}
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:19
@@ -132,6 +192,11 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                   |       value borrowed here after move
    |                   value moved into `b` here
    |                   move occurs because `b` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         a @ Some((ref mut b @ ref mut c, d @ ref e)) => {}
+   |                   +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38
@@ -142,6 +207,11 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                                      |   value borrowed here after move
    |                                      value moved into `d` here
    |                                      move occurs because `d` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         a @ Some((mut b @ ref mut c, ref d @ ref e)) => {}
+   |                                      +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:9
@@ -153,6 +223,11 @@ LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         |             value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref mut a @ Some([ref b, ref mut c]) => {}
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9
@@ -163,6 +238,11 @@ LL |         a @ Some(ref b) => {}
    |         |        value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref a @ Some(ref b) => {}
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:9
@@ -174,6 +254,11 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         |                 value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref a @ Some((mut b @ ref mut c, d @ ref e)) => {}
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:19
@@ -184,6 +269,11 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                   |       value borrowed here after move
    |                   value moved into `b` here
    |                   move occurs because `b` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         a @ Some((ref mut b @ ref mut c, d @ ref e)) => {}
+   |                   +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38
@@ -194,6 +284,11 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                                      |   value borrowed here after move
    |                                      value moved into `d` here
    |                                      move occurs because `d` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         a @ Some((mut b @ ref mut c, ref d @ ref e)) => {}
+   |                                      +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:9
@@ -205,6 +300,11 @@ LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         |             value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref mut a @ Some([ref b, ref mut c]) => {}
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:11:11
@@ -215,6 +315,11 @@ LL |     fn f1(a @ ref b: U) {}
    |           |   value borrowed here after move
    |           value moved into `a` here
    |           move occurs because `a` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     fn f1(ref a @ ref b: U) {}
+   |           +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11
@@ -226,6 +331,11 @@ LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |           |            value borrowed here after move
    |           value moved into `a` here
    |           move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     fn f2(ref mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
+   |           +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:20
@@ -236,6 +346,11 @@ LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |                    |   value borrowed here after move
    |                    value moved into `b` here
    |                    move occurs because `b` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     fn f2(mut a @ (ref b @ ref c, mut d @ ref e): (U, U)) {}
+   |                    +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:31
@@ -246,6 +361,11 @@ LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |                               |       value borrowed here after move
    |                               value moved into `d` here
    |                               move occurs because `d` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     fn f2(mut a @ (b @ ref c, ref mut d @ ref e): (U, U)) {}
+   |                               +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:19:11
@@ -257,6 +377,11 @@ LL |     fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
    |           |    value borrowed here after move
    |           value moved into `a` here
    |           move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     fn f3(ref a @ [ref mut b, ref c]: [U; 2]) {}
+   |           +++
 
 error[E0382]: use of partially moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:9
@@ -267,6 +392,10 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |         value used here after partial move
    |
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ (mut b @ ref mut c, ref d @ ref e) = (U, U);
+   |         +++                         +++
 
 error[E0382]: use of partially moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:9
@@ -277,6 +406,10 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |         value used here after partial move
    |
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ (mut b @ ref mut c, ref d @ ref e) = (u(), u());
+   |         +++                         +++
 
 error[E0382]: use of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38
@@ -285,6 +418,11 @@ LL |     match Some((U, U)) {
    |           ------------ move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         - value moved here           ^ value used here after move
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref a @ Some((mut b @ ref mut c, d @ ref e)) => {}
+   |         +++
 
 error[E0382]: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:30
@@ -305,6 +443,11 @@ LL |         a @ Some(ref b) => {}
    |         -        ^^^^^ value borrowed here after move
    |         |
    |         value moved here
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref a @ Some(ref b) => {}
+   |         +++
 
 error[E0382]: use of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38
@@ -313,6 +456,11 @@ LL |     match Some((u(), u())) {
    |           ---------------- move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         - value moved here           ^ value used here after move
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref a @ Some((mut b @ ref mut c, d @ ref e)) => {}
+   |         +++
 
 error[E0382]: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:30
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
index b2f22fe8638..770bb89530c 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
@@ -242,6 +242,10 @@ LL |     let ref mut a @ [b, mut c] = [U, U];
    |         value borrowed here after partial move
    |
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref mut a @ [b, ref mut c] = [U, U];
+   |                         +++
 
 error[E0382]: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref.rs:33:9
@@ -251,6 +255,11 @@ LL |     let ref a @ b = u();
    |         |       |
    |         |       value moved here
    |         value borrowed here after move
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ ref b = u();
+   |                 +++
 
 error[E0382]: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref.rs:36:18
@@ -261,6 +270,10 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |                  value borrowed here after move
    |
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ (ref b @ ref mut c, ref d @ e) = (u(), u());
+   |                          +++
 
 error[E0382]: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref.rs:36:33
@@ -271,6 +284,10 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |                                 value borrowed here after move
    |
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ (ref b @ mut c, ref d @ ref e) = (u(), u());
+   |                                         +++
 
 error[E0382]: borrow of partially moved value
   --> $DIR/borrowck-pat-by-move-and-ref.rs:42:9
@@ -281,6 +298,10 @@ LL |     let ref mut a @ [b, mut c] = [u(), u()];
    |         value borrowed here after partial move
    |
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref mut a @ [b, ref mut c] = [u(), u()];
+   |                         +++
 
 error[E0382]: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23
@@ -291,7 +312,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                       value borrowed here after move
    |
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
-help: borrow this field in the pattern to avoid moving the value
+help: borrow this binding in the pattern to avoid moving the value
    |
 LL |         ref a @ Some((ref b @ ref mut c, ref d @ e)) => {}
    |                               +++
@@ -305,7 +326,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                                      value borrowed here after move
    |
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
-help: borrow this field in the pattern to avoid moving the value
+help: borrow this binding in the pattern to avoid moving the value
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ ref e)) => {}
    |                                              +++
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
index 384a57b2ee0..ad4ce7952ca 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
@@ -97,6 +97,11 @@ LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         |    value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-ref-mut-twice.rs:67:9
@@ -109,6 +114,11 @@ LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         |    value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `&mut (U, [U; 2])` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ (b, [c, d]) = &mut val; // Same as ^--
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9
@@ -119,6 +129,11 @@ LL |     let a @ &mut ref mut b = &mut U;
    |         |        value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `&mut U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ &mut ref mut b = &mut U;
+   |         +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-ref-mut-twice.rs:72:9
@@ -130,6 +145,11 @@ LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         |         value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `&mut (U, U)` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ &mut (ref mut b, ref mut c) = &mut (U, U);
+   |         +++
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:76:9
diff --git a/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr b/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr
index cd3234952fa..e0e623fa544 100644
--- a/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr
+++ b/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr
@@ -7,6 +7,10 @@ LL |     let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C));
    |         value used here after partial move
    |
    = note: partial move occurs because value has type `NC<C, C>`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref a @ NC(b, ref c @ NC(d, e)) = NC(C, NC(C, C));
+   |         +++           +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
index 840a513d6c6..638bdd6db76 100644
--- a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
+++ b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
@@ -34,6 +34,11 @@ LL |         Ok(ref a @ b) | Err(b @ ref a) => {
    |                             |   value borrowed here after move
    |                             value moved into `b` here
    |                             move occurs because `b` has type `NotCopy` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         Ok(ref a @ b) | Err(ref b @ ref a) => {
+   |                             +++
 
 error: cannot move out of value because it is borrowed
   --> $DIR/default-binding-modes-both-sides-independent.rs:42:9
@@ -52,6 +57,11 @@ LL |     let ref mut a @ b = NotCopy;
    |         |           |
    |         |           value moved here
    |         value borrowed here after move
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref mut a @ ref b = NotCopy;
+   |                     +++
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr
index bac2db6ce82..bb7b818368b 100644
--- a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr
+++ b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr
@@ -129,6 +129,10 @@ LL |     drop(tup.1);
    |          ^^^^^ value used here after move
    |
    = note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let (ref _x0, ref _x1, ref _x2, ..) = tup;
+   |                   +++
 
 error[E0382]: borrow of moved value: `tup.1`
   --> $DIR/borrowck-move-ref-pattern.rs:29:20
diff --git a/src/test/ui/pattern/pattern-binding-disambiguation.rs b/src/test/ui/pattern/pattern-binding-disambiguation.rs
index 2e80ea345dc..ce1d8c6c047 100644
--- a/src/test/ui/pattern/pattern-binding-disambiguation.rs
+++ b/src/test/ui/pattern/pattern-binding-disambiguation.rs
@@ -33,7 +33,7 @@ fn main() {
         TupleVariant => {} //~ ERROR match bindings cannot shadow tuple variants
     }
     match doesnt_matter {
-        BracedVariant => {} //~ ERROR match bindings cannot shadow struct variants
+        BracedVariant => {} // OK, `BracedVariant` is a fresh binding
     }
     match CONST {
         CONST => {} // OK, `CONST` is a const pattern
@@ -50,7 +50,7 @@ fn main() {
     let BracedStruct = doesnt_matter; // OK, `BracedStruct` is a fresh binding
     let UnitVariant = UnitVariant; // OK, `UnitVariant` is a unit variant pattern
     let TupleVariant = doesnt_matter; //~ ERROR let bindings cannot shadow tuple variants
-    let BracedVariant = doesnt_matter; //~ ERROR let bindings cannot shadow struct variants
+    let BracedVariant = doesnt_matter; // OK, `BracedVariant` is a fresh binding
     let CONST = CONST; // OK, `CONST` is a const pattern
     let STATIC = doesnt_matter; //~ ERROR let bindings cannot shadow statics
     let function = doesnt_matter; // OK, `function` is a fresh binding
diff --git a/src/test/ui/pattern/pattern-binding-disambiguation.stderr b/src/test/ui/pattern/pattern-binding-disambiguation.stderr
index 1529e538b55..d54467b3c0c 100644
--- a/src/test/ui/pattern/pattern-binding-disambiguation.stderr
+++ b/src/test/ui/pattern/pattern-binding-disambiguation.stderr
@@ -22,15 +22,6 @@ LL |         TupleVariant => {}
    |         cannot be named the same as a tuple variant
    |         help: try specify the pattern arguments: `TupleVariant(..)`
 
-error[E0530]: match bindings cannot shadow struct variants
-  --> $DIR/pattern-binding-disambiguation.rs:36:9
-   |
-LL | use E::*;
-   |     ---- the struct variant `BracedVariant` is imported here
-...
-LL |         BracedVariant => {}
-   |         ^^^^^^^^^^^^^ cannot be named the same as a struct variant
-
 error[E0530]: match bindings cannot shadow statics
   --> $DIR/pattern-binding-disambiguation.rs:42:9
    |
@@ -58,15 +49,6 @@ LL | use E::*;
 LL |     let TupleVariant = doesnt_matter;
    |         ^^^^^^^^^^^^ cannot be named the same as a tuple variant
 
-error[E0530]: let bindings cannot shadow struct variants
-  --> $DIR/pattern-binding-disambiguation.rs:53:9
-   |
-LL | use E::*;
-   |     ---- the struct variant `BracedVariant` is imported here
-...
-LL |     let BracedVariant = doesnt_matter;
-   |         ^^^^^^^^^^^^^ cannot be named the same as a struct variant
-
 error[E0530]: let bindings cannot shadow statics
   --> $DIR/pattern-binding-disambiguation.rs:55:9
    |
@@ -76,6 +58,6 @@ LL | static STATIC: () = ();
 LL |     let STATIC = doesnt_matter;
    |         ^^^^^^ cannot be named the same as a static
 
-error: aborting due to 8 previous errors
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/privacy/effective_visibilities.rs b/src/test/ui/privacy/effective_visibilities.rs
index 4479b0d8f61..8d0602fa79f 100644
--- a/src/test/ui/privacy/effective_visibilities.rs
+++ b/src/test/ui/privacy/effective_visibilities.rs
@@ -17,13 +17,13 @@ mod outer { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub
         }
 
         #[rustc_effective_visibility]
-        struct PrivStruct; //~ ERROR not in the table
-                           //~| ERROR not in the table
+        struct PrivStruct; //~ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
+                           //~| ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
 
         #[rustc_effective_visibility]
         pub union PubUnion { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
             #[rustc_effective_visibility]
-            a: u8, //~ ERROR not in the table
+            a: u8, //~ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
             #[rustc_effective_visibility]
             pub b: u8, //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
         }
diff --git a/src/test/ui/privacy/effective_visibilities.stderr b/src/test/ui/privacy/effective_visibilities.stderr
index 019aaf8086a..6a99afe64fe 100644
--- a/src/test/ui/privacy/effective_visibilities.stderr
+++ b/src/test/ui/privacy/effective_visibilities.stderr
@@ -22,13 +22,13 @@ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImpl
 LL |         pub trait PubTrait {
    |         ^^^^^^^^^^^^^^^^^^
 
-error: not in the table
+error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
   --> $DIR/effective_visibilities.rs:20:9
    |
 LL |         struct PrivStruct;
    |         ^^^^^^^^^^^^^^^^^
 
-error: not in the table
+error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
   --> $DIR/effective_visibilities.rs:20:9
    |
 LL |         struct PrivStruct;
@@ -40,7 +40,7 @@ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImpl
 LL |         pub union PubUnion {
    |         ^^^^^^^^^^^^^^^^^^
 
-error: not in the table
+error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
   --> $DIR/effective_visibilities.rs:26:13
    |
 LL |             a: u8,
diff --git a/src/test/ui/privacy/effective_visibilities_invariants.rs b/src/test/ui/privacy/effective_visibilities_invariants.rs
new file mode 100644
index 00000000000..af5a2bed6ab
--- /dev/null
+++ b/src/test/ui/privacy/effective_visibilities_invariants.rs
@@ -0,0 +1,12 @@
+// Invariant checking doesn't ICE in some cases with errors (issue #104249).
+
+#![feature(staged_api)] //~ ERROR module has missing stability attribute
+
+pub mod m {} //~ ERROR module has missing stability attribute
+
+pub mod m { //~ ERROR the name `m` is defined multiple times
+    mod inner {}
+    type Inner = u8;
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/effective_visibilities_invariants.stderr b/src/test/ui/privacy/effective_visibilities_invariants.stderr
new file mode 100644
index 00000000000..fd205f4058a
--- /dev/null
+++ b/src/test/ui/privacy/effective_visibilities_invariants.stderr
@@ -0,0 +1,32 @@
+error[E0428]: the name `m` is defined multiple times
+  --> $DIR/effective_visibilities_invariants.rs:7:1
+   |
+LL | pub mod m {}
+   | --------- previous definition of the module `m` here
+LL |
+LL | pub mod m {
+   | ^^^^^^^^^ `m` redefined here
+   |
+   = note: `m` must be defined only once in the type namespace of this module
+
+error: module has missing stability attribute
+  --> $DIR/effective_visibilities_invariants.rs:3:1
+   |
+LL | / #![feature(staged_api)]
+LL | |
+LL | | pub mod m {}
+LL | |
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: module has missing stability attribute
+  --> $DIR/effective_visibilities_invariants.rs:5:1
+   |
+LL | pub mod m {}
+   | ^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/qualified/qualified-path-params.stderr b/src/test/ui/qualified/qualified-path-params.stderr
index 82cc6e19f9d..a49ed6c8f60 100644
--- a/src/test/ui/qualified/qualified-path-params.stderr
+++ b/src/test/ui/qualified/qualified-path-params.stderr
@@ -2,7 +2,7 @@ error[E0533]: expected unit struct, unit variant or constant, found associated f
   --> $DIR/qualified-path-params.rs:20:9
    |
 LL |         <S as Tr>::A::f::<u8> => {}
-   |         ^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^ not a unit struct, unit variant or constant
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/qualified-path-params.rs:22:15
diff --git a/src/test/ui/recursion/issue-83150.stderr b/src/test/ui/recursion/issue-83150.stderr
index a67bfd018a2..4d00a708313 100644
--- a/src/test/ui/recursion/issue-83150.stderr
+++ b/src/test/ui/recursion/issue-83150.stderr
@@ -9,11 +9,9 @@ LL |     func(&mut iter.map(|x| x + 1))
    = help: a `loop` may express intention better if this is on purpose
    = note: `#[warn(unconditional_recursion)]` on by default
 
-error[E0275]: overflow evaluating the requirement `<std::ops::Range<u8> as Iterator>::Item`
+error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>: Iterator`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
-   = note: required for `Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:12:24: 12:27]>` to implement `Iterator`
-   = note: 64 redundant requirements hidden
    = note: required for `&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>` to implement `Iterator`
    = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type-hash.txt'
 
diff --git a/src/test/ui/recursion/issue-95134.rs b/src/test/ui/recursion/issue-95134.rs
index adc9c6ee2d9..fdc4d536981 100644
--- a/src/test/ui/recursion/issue-95134.rs
+++ b/src/test/ui/recursion/issue-95134.rs
@@ -1,6 +1,8 @@
 // build-fail
+// known-bug: #95134
 // compile-flags: -Copt-level=0
-//~^^ ERROR overflow evaluating the requirement
+// failure-status: 101
+// dont-check-compiler-stderr
 
 pub fn encode_num<Writer: ExampleWriter>(n: u32, mut writer: Writer) -> Result<(), Writer::Error> {
     if n > 15 {
diff --git a/src/test/ui/recursion/issue-95134.stderr b/src/test/ui/recursion/issue-95134.stderr
deleted file mode 100644
index 57a498694b7..00000000000
--- a/src/test/ui/recursion/issue-95134.stderr
+++ /dev/null
@@ -1,7 +0,0 @@
-error[E0275]: overflow evaluating the requirement `<EmptyWriter as ExampleWriter>::Error`
-   |
-   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_95134`)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/resolve/issue-18252.rs b/src/test/ui/resolve/issue-18252.rs
index af0a3cbcb2d..f6ebe292076 100644
--- a/src/test/ui/resolve/issue-18252.rs
+++ b/src/test/ui/resolve/issue-18252.rs
@@ -4,5 +4,5 @@ enum Foo {
 
 fn main() {
     let f = Foo::Variant(42);
-    //~^ ERROR expected function, tuple struct or tuple variant, found struct variant `Foo::Variant`
+    //~^ ERROR expected value, found struct variant `Foo::Variant`
 }
diff --git a/src/test/ui/resolve/issue-18252.stderr b/src/test/ui/resolve/issue-18252.stderr
index 13e7a59732d..d9006c0a6c2 100644
--- a/src/test/ui/resolve/issue-18252.stderr
+++ b/src/test/ui/resolve/issue-18252.stderr
@@ -1,12 +1,9 @@
-error[E0423]: expected function, tuple struct or tuple variant, found struct variant `Foo::Variant`
+error[E0533]: expected value, found struct variant `Foo::Variant`
   --> $DIR/issue-18252.rs:6:13
    |
-LL |     Variant { x: usize }
-   |     -------------------- `Foo::Variant` defined here
-...
 LL |     let f = Foo::Variant(42);
-   |             ^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `Foo::Variant { x: val }`
+   |             ^^^^^^^^^^^^ not a value
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0423`.
+For more information about this error, try `rustc --explain E0533`.
diff --git a/src/test/ui/resolve/issue-19452.stderr b/src/test/ui/resolve/issue-19452.stderr
index 8df84067e67..eff89241fd2 100644
--- a/src/test/ui/resolve/issue-19452.stderr
+++ b/src/test/ui/resolve/issue-19452.stderr
@@ -1,23 +1,15 @@
-error[E0423]: expected value, found struct variant `Homura::Madoka`
+error[E0533]: expected value, found struct variant `Homura::Madoka`
   --> $DIR/issue-19452.rs:10:18
    |
-LL |     Madoka { age: u32 }
-   |     ------------------- `Homura::Madoka` defined here
-...
 LL |     let homura = Homura::Madoka;
-   |                  ^^^^^^^^^^^^^^ help: use struct literal syntax instead: `Homura::Madoka { age: val }`
+   |                  ^^^^^^^^^^^^^^ not a value
 
-error[E0423]: expected value, found struct variant `issue_19452_aux::Homura::Madoka`
+error[E0533]: expected value, found struct variant `issue_19452_aux::Homura::Madoka`
   --> $DIR/issue-19452.rs:13:18
    |
 LL |     let homura = issue_19452_aux::Homura::Madoka;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `issue_19452_aux::Homura::Madoka { /* fields */ }`
-   |
-  ::: $DIR/auxiliary/issue-19452-aux.rs:2:5
-   |
-LL |     Madoka { age: u32 }
-   |     ------ `issue_19452_aux::Homura::Madoka` defined here
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a value
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0423`.
+For more information about this error, try `rustc --explain E0533`.
diff --git a/src/test/ui/resolve/issue-73427.stderr b/src/test/ui/resolve/issue-73427.stderr
index d31c5e47775..4af5f29d809 100644
--- a/src/test/ui/resolve/issue-73427.stderr
+++ b/src/test/ui/resolve/issue-73427.stderr
@@ -17,16 +17,12 @@ LL | | }
    | |_^
 help: you might have meant to use one of the following enum variants
    |
-LL |     (A::Struct {}).foo();
-   |     ~~~~~~~~~~~~~~
 LL |     (A::Tuple()).foo();
    |     ~~~~~~~~~~~~
 LL |     A::Unit.foo();
    |     ~~~~~~~
-help: alternatively, the following enum variants are also available
+help: alternatively, the following enum variant is available
    |
-LL |     (A::StructWithFields { /* fields */ }).foo();
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 LL |     (A::TupleWithFields(/* fields */)).foo();
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -34,7 +30,7 @@ error[E0423]: expected value, found enum `B`
   --> $DIR/issue-73427.rs:35:5
    |
 LL |     B.foo();
-   |     ^
+   |     ^ help: the following enum variant is available: `(B::TupleWithFields(/* fields */))`
    |
 note: the enum is defined here
   --> $DIR/issue-73427.rs:9:1
@@ -44,12 +40,6 @@ LL | |     StructWithFields { x: () },
 LL | |     TupleWithFields(()),
 LL | | }
    | |_^
-help: the following enum variants are available
-   |
-LL |     (B::StructWithFields { /* fields */ }).foo();
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LL |     (B::TupleWithFields(/* fields */)).foo();
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0423]: expected value, found enum `C`
   --> $DIR/issue-73427.rs:37:5
@@ -70,10 +60,8 @@ help: you might have meant to use the following enum variant
    |
 LL |     C::Unit.foo();
    |     ~~~~~~~
-help: alternatively, the following enum variants are also available
+help: alternatively, the following enum variant is available
    |
-LL |     (C::StructWithFields { /* fields */ }).foo();
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 LL |     (C::TupleWithFields(/* fields */)).foo();
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -130,7 +118,7 @@ error[E0532]: expected tuple struct or tuple variant, found enum `A`
 LL |     if let A(3) = x { }
    |            ^
    |
-   = help: you might have meant to match against one of the enum's non-tuple variants
+   = help: you might have meant to match against the enum's non-tuple variant
 note: the enum is defined here
   --> $DIR/issue-73427.rs:1:1
    |
@@ -155,7 +143,7 @@ error[E0423]: expected function, tuple struct or tuple variant, found enum `A`
 LL |     let x = A(3);
    |             ^
    |
-   = help: you might have meant to construct one of the enum's non-tuple variants
+   = help: you might have meant to construct the enum's non-tuple variant
 note: the enum is defined here
   --> $DIR/issue-73427.rs:1:1
    |
diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr
index 82a4211f08a..d734fa76b4a 100644
--- a/src/test/ui/resolve/privacy-enum-ctor.stderr
+++ b/src/test/ui/resolve/privacy-enum-ctor.stderr
@@ -19,12 +19,10 @@ help: you might have meant to use the following enum variant
    |
 LL |         m::Z::Unit;
    |         ~~~~~~~~~~
-help: alternatively, the following enum variants are also available
+help: alternatively, the following enum variant is available
    |
 LL |         (m::Z::Fn(/* fields */));
    |         ~~~~~~~~~~~~~~~~~~~~~~~~
-LL |         (m::Z::Struct { /* fields */ });
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0423]: expected value, found enum `Z`
   --> $DIR/privacy-enum-ctor.rs:25:9
@@ -47,23 +45,10 @@ help: you might have meant to use the following enum variant
    |
 LL |         m::Z::Unit;
    |         ~~~~~~~~~~
-help: alternatively, the following enum variants are also available
+help: alternatively, the following enum variant is available
    |
 LL |         (m::Z::Fn(/* fields */));
    |         ~~~~~~~~~~~~~~~~~~~~~~~~
-LL |         (m::Z::Struct { /* fields */ });
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-error[E0423]: expected value, found struct variant `Z::Struct`
-  --> $DIR/privacy-enum-ctor.rs:29:20
-   |
-LL | /             Struct {
-LL | |                 s: u8,
-LL | |             },
-   | |_____________- `Z::Struct` defined here
-...
-LL |           let _: Z = Z::Struct;
-   |                      ^^^^^^^^^ help: use struct literal syntax instead: `Z::Struct { s: val }`
 
 error[E0423]: expected value, found enum `m::E`
   --> $DIR/privacy-enum-ctor.rs:41:16
@@ -89,12 +74,10 @@ help: you might have meant to use the following enum variant
    |
 LL |     let _: E = E::Unit;
    |                ~~~~~~~
-help: alternatively, the following enum variants are also available
+help: alternatively, the following enum variant is available
    |
 LL |     let _: E = (E::Fn(/* fields */));
    |                ~~~~~~~~~~~~~~~~~~~~~
-LL |     let _: E = (E::Struct { /* fields */ });
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 help: a function with a similar name exists
    |
 LL |     let _: E = m::f;
@@ -111,17 +94,6 @@ LL -     let _: E = m::E;
 LL +     let _: E = E;
    |
 
-error[E0423]: expected value, found struct variant `m::E::Struct`
-  --> $DIR/privacy-enum-ctor.rs:45:16
-   |
-LL | /         Struct {
-LL | |             s: u8,
-LL | |         },
-   | |_________- `m::E::Struct` defined here
-...
-LL |       let _: E = m::E::Struct;
-   |                  ^^^^^^^^^^^^ help: use struct literal syntax instead: `m::E::Struct { s: val }`
-
 error[E0423]: expected value, found enum `E`
   --> $DIR/privacy-enum-ctor.rs:49:16
    |
@@ -143,12 +115,10 @@ help: you might have meant to use the following enum variant
    |
 LL |     let _: E = E::Unit;
    |                ~~~~~~~
-help: alternatively, the following enum variants are also available
+help: alternatively, the following enum variant is available
    |
 LL |     let _: E = (E::Fn(/* fields */));
    |                ~~~~~~~~~~~~~~~~~~~~~
-LL |     let _: E = (E::Struct { /* fields */ });
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 help: consider importing one of these items instead
    |
 LL | use std::f32::consts::E;
@@ -156,17 +126,6 @@ LL | use std::f32::consts::E;
 LL | use std::f64::consts::E;
    |
 
-error[E0423]: expected value, found struct variant `E::Struct`
-  --> $DIR/privacy-enum-ctor.rs:53:16
-   |
-LL | /         Struct {
-LL | |             s: u8,
-LL | |         },
-   | |_________- `E::Struct` defined here
-...
-LL |       let _: E = E::Struct;
-   |                  ^^^^^^^^^ help: use struct literal syntax instead: `E::Struct { s: val }`
-
 error[E0412]: cannot find type `Z` in this scope
   --> $DIR/privacy-enum-ctor.rs:57:12
    |
@@ -203,12 +162,10 @@ help: you might have meant to use the following enum variant
    |
 LL |     let _: Z = m::Z::Unit;
    |                ~~~~~~~~~~
-help: alternatively, the following enum variants are also available
+help: alternatively, the following enum variant is available
    |
 LL |     let _: Z = (m::Z::Fn(/* fields */));
    |                ~~~~~~~~~~~~~~~~~~~~~~~~
-LL |     let _: Z = (m::Z::Struct { /* fields */ });
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0412]: cannot find type `Z` in this scope
   --> $DIR/privacy-enum-ctor.rs:61:12
@@ -240,17 +197,6 @@ note: enum `m::Z` exists but is inaccessible
 LL |         pub(in m) enum Z {
    |         ^^^^^^^^^^^^^^^^ not accessible
 
-error[E0423]: expected value, found struct variant `m::n::Z::Struct`
-  --> $DIR/privacy-enum-ctor.rs:64:16
-   |
-LL | /             Struct {
-LL | |                 s: u8,
-LL | |             },
-   | |_____________- `m::n::Z::Struct` defined here
-...
-LL |       let _: Z = m::n::Z::Struct;
-   |                  ^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `m::n::Z::Struct { s: val }`
-
 error[E0412]: cannot find type `Z` in this scope
   --> $DIR/privacy-enum-ctor.rs:68:12
    |
@@ -332,6 +278,12 @@ help: use parentheses to construct this tuple variant
 LL |         let _: Z = Z::Fn(/* u8 */);
    |                         ++++++++++
 
+error[E0533]: expected value, found struct variant `Z::Struct`
+  --> $DIR/privacy-enum-ctor.rs:29:20
+   |
+LL |         let _: Z = Z::Struct;
+   |                    ^^^^^^^^^ not a value
+
 error[E0618]: expected function, found enum variant `Z::Unit`
   --> $DIR/privacy-enum-ctor.rs:31:17
    |
@@ -367,6 +319,12 @@ help: use parentheses to construct this tuple variant
 LL |     let _: E = m::E::Fn(/* u8 */);
    |                        ++++++++++
 
+error[E0533]: expected value, found struct variant `m::E::Struct`
+  --> $DIR/privacy-enum-ctor.rs:45:16
+   |
+LL |     let _: E = m::E::Struct;
+   |                ^^^^^^^^^^^^ not a value
+
 error[E0618]: expected function, found enum variant `m::E::Unit`
   --> $DIR/privacy-enum-ctor.rs:47:16
    |
@@ -402,6 +360,12 @@ help: use parentheses to construct this tuple variant
 LL |     let _: E = E::Fn(/* u8 */);
    |                     ++++++++++
 
+error[E0533]: expected value, found struct variant `E::Struct`
+  --> $DIR/privacy-enum-ctor.rs:53:16
+   |
+LL |     let _: E = E::Struct;
+   |                ^^^^^^^^^ not a value
+
 error[E0618]: expected function, found enum variant `E::Unit`
   --> $DIR/privacy-enum-ctor.rs:55:16
    |
@@ -419,7 +383,13 @@ LL -     let _: E = E::Unit();
 LL +     let _: E = E::Unit;
    |
 
+error[E0533]: expected value, found struct variant `m::n::Z::Struct`
+  --> $DIR/privacy-enum-ctor.rs:64:16
+   |
+LL |     let _: Z = m::n::Z::Struct;
+   |                ^^^^^^^^^^^^^^^ not a value
+
 error: aborting due to 23 previous errors
 
-Some errors have detailed explanations: E0308, E0412, E0423, E0603, E0618.
+Some errors have detailed explanations: E0308, E0412, E0423, E0533, E0603, E0618.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/rfc-2294-if-let-guard/run-pass.rs b/src/test/ui/rfc-2294-if-let-guard/run-pass.rs
index 3da57989df2..a303a0d1fce 100644
--- a/src/test/ui/rfc-2294-if-let-guard/run-pass.rs
+++ b/src/test/ui/rfc-2294-if-let-guard/run-pass.rs
@@ -30,4 +30,11 @@ fn main() {
         Some(x) if let Foo::Qux(y) = qux(x) => assert_eq!(y, 84),
         _ => panic!(),
     }
+
+    // issue #88015
+    #[allow(irrefutable_let_patterns)]
+    match () {
+        () | () if let x = 42 => assert_eq!(x, 42),
+        _ => panic!()
+    }
 }
diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr
index 5611b5f4ece..06699b947be 100644
--- a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr
+++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr
@@ -7,6 +7,12 @@ LL |     let _ = dbg!(a);
    |             ------- value moved here
 LL |     let _ = dbg!(a);
    |                  ^ value used here after move
+   |
+help: borrow this binding in the pattern to avoid moving the value
+  --> $SRC_DIR/std/src/macros.rs:LL:COL
+   |
+LL |             ref tmp => {
+   |             +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2497-if-let-chains/issue-99938.rs b/src/test/ui/rfc-2497-if-let-chains/issue-99938.rs
new file mode 100644
index 00000000000..bd81ce0b19c
--- /dev/null
+++ b/src/test/ui/rfc-2497-if-let-chains/issue-99938.rs
@@ -0,0 +1,31 @@
+// compile-flags: -Zvalidate-mir -C opt-level=3
+// build-pass
+#![feature(let_chains)]
+struct TupleIter<T, I: Iterator<Item = T>> {
+    inner: I,
+}
+
+impl<T, I: Iterator<Item = T>> Iterator for TupleIter<T, I> {
+    type Item = (T, T, T);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let inner = &mut self.inner;
+
+        if let Some(first) = inner.next()
+            && let Some(second) = inner.next()
+            && let Some(third) = inner.next()
+        {
+            Some((first, second, third))
+        } else {
+            None
+        }
+    }
+}
+
+fn main() {
+    let vec: Vec<u8> = Vec::new();
+    let mut tup_iter = TupleIter {
+        inner: vec.into_iter(),
+    };
+    tup_iter.next();
+}
diff --git a/src/test/ui/stats/hir-stats.rs b/src/test/ui/stats/hir-stats.rs
index a24b3ada57e..0b89d0b160b 100644
--- a/src/test/ui/stats/hir-stats.rs
+++ b/src/test/ui/stats/hir-stats.rs
@@ -1,6 +1,7 @@
 // check-pass
 // compile-flags: -Zhir-stats
 // only-x86_64
+// ignore-stage1  FIXME: remove after next bootstrap bump
 
 // The aim here is to include at least one of every different type of top-level
 // AST/HIR node reported by `-Zhir-stats`.
diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr
index 297245f0198..012bc848d4b 100644
--- a/src/test/ui/stats/hir-stats.stderr
+++ b/src/test/ui/stats/hir-stats.stderr
@@ -2,12 +2,12 @@ ast-stats-1 PRE EXPANSION AST STATS
 ast-stats-1 Name                Accumulated Size         Count     Item Size
 ast-stats-1 ----------------------------------------------------------------
 ast-stats-1 ExprField                 48 ( 0.6%)             1            48
+ast-stats-1 GenericArgs               56 ( 0.8%)             1            56
+ast-stats-1 - AngleBracketed            56 ( 0.8%)             1
 ast-stats-1 Crate                     56 ( 0.8%)             1            56
 ast-stats-1 Attribute                 64 ( 0.9%)             2            32
 ast-stats-1 - Normal                    32 ( 0.4%)             1
 ast-stats-1 - DocComment                32 ( 0.4%)             1
-ast-stats-1 GenericArgs               64 ( 0.9%)             1            64
-ast-stats-1 - AngleBracketed            64 ( 0.9%)             1
 ast-stats-1 Local                     72 ( 1.0%)             1            72
 ast-stats-1 WherePredicate            72 ( 1.0%)             1            72
 ast-stats-1 - BoundPredicate            72 ( 1.0%)             1
@@ -53,15 +53,15 @@ ast-stats-1 - Impl                     184 ( 2.5%)             1
 ast-stats-1 - Fn                       368 ( 5.0%)             2
 ast-stats-1 - Use                      552 ( 7.4%)             3
 ast-stats-1 ----------------------------------------------------------------
-ast-stats-1 Total                  7_424
+ast-stats-1 Total                  7_416
 ast-stats-1
 ast-stats-2 POST EXPANSION AST STATS
 ast-stats-2 Name                Accumulated Size         Count     Item Size
 ast-stats-2 ----------------------------------------------------------------
 ast-stats-2 ExprField                 48 ( 0.6%)             1            48
+ast-stats-2 GenericArgs               56 ( 0.7%)             1            56
+ast-stats-2 - AngleBracketed            56 ( 0.7%)             1
 ast-stats-2 Crate                     56 ( 0.7%)             1            56
-ast-stats-2 GenericArgs               64 ( 0.8%)             1            64
-ast-stats-2 - AngleBracketed            64 ( 0.8%)             1
 ast-stats-2 Local                     72 ( 0.9%)             1            72
 ast-stats-2 WherePredicate            72 ( 0.9%)             1            72
 ast-stats-2 - BoundPredicate            72 ( 0.9%)             1
@@ -80,9 +80,9 @@ ast-stats-2 - Expr                      96 ( 1.2%)             3
 ast-stats-2 Param                    160 ( 2.0%)             4            40
 ast-stats-2 FnDecl                   200 ( 2.5%)             5            40
 ast-stats-2 Variant                  240 ( 3.0%)             2           120
-ast-stats-2 GenericBound             288 ( 3.5%)             4            72
-ast-stats-2 - Trait                    288 ( 3.5%)             4
-ast-stats-2 Block                    288 ( 3.5%)             6            48
+ast-stats-2 GenericBound             288 ( 3.6%)             4            72
+ast-stats-2 - Trait                    288 ( 3.6%)             4
+ast-stats-2 Block                    288 ( 3.6%)             6            48
 ast-stats-2 AssocItem                416 ( 5.1%)             4           104
 ast-stats-2 - Type                     208 ( 2.6%)             2
 ast-stats-2 - Fn                       208 ( 2.6%)             2
@@ -104,7 +104,7 @@ ast-stats-2 - Rptr                      64 ( 0.8%)             1
 ast-stats-2 - Ptr                       64 ( 0.8%)             1
 ast-stats-2 - ImplicitSelf             128 ( 1.6%)             2
 ast-stats-2 - Path                     640 ( 7.9%)            10
-ast-stats-2 Item                   2_024 (24.9%)            11           184
+ast-stats-2 Item                   2_024 (25.0%)            11           184
 ast-stats-2 - Trait                    184 ( 2.3%)             1
 ast-stats-2 - Enum                     184 ( 2.3%)             1
 ast-stats-2 - ExternCrate              184 ( 2.3%)             1
@@ -113,7 +113,7 @@ ast-stats-2 - Impl                     184 ( 2.3%)             1
 ast-stats-2 - Fn                       368 ( 4.5%)             2
 ast-stats-2 - Use                      736 ( 9.1%)             4
 ast-stats-2 ----------------------------------------------------------------
-ast-stats-2 Total                  8_120
+ast-stats-2 Total                  8_112
 ast-stats-2
 hir-stats HIR STATS
 hir-stats Name                Accumulated Size         Count     Item Size
diff --git a/src/test/ui/structs-enums/type-sizes.rs b/src/test/ui/structs-enums/type-sizes.rs
index 7a23f13630a..63e2f3150c0 100644
--- a/src/test/ui/structs-enums/type-sizes.rs
+++ b/src/test/ui/structs-enums/type-sizes.rs
@@ -3,6 +3,7 @@
 #![allow(non_camel_case_types)]
 #![allow(dead_code)]
 #![feature(never_type)]
+#![feature(pointer_is_aligned)]
 
 use std::mem::size_of;
 use std::num::NonZeroU8;
@@ -168,6 +169,18 @@ pub enum EnumManyVariant<X> {
     _F0, _F1, _F2, _F3, _F4, _F5, _F6, _F7, _F8, _F9, _FA, _FB, _FC, _FD, _FE, _FF,
 }
 
+struct Reorder4 {
+    a: u32,
+    b: u8,
+    ary: [u8; 4],
+}
+
+struct Reorder2 {
+    a: u16,
+    b: u8,
+    ary: [u8; 6],
+}
+
 pub fn main() {
     assert_eq!(size_of::<u8>(), 1 as usize);
     assert_eq!(size_of::<u32>(), 4 as usize);
@@ -249,4 +262,12 @@ pub fn main() {
     assert_eq!(size_of::<EnumManyVariant<Option<NicheU16>>>(), 4);
     assert_eq!(size_of::<EnumManyVariant<Option2<NicheU16,u8>>>(), 6);
     assert_eq!(size_of::<EnumManyVariant<Option<(NicheU16,u8)>>>(), 6);
+
+
+    let v = Reorder4 {a: 0, b: 0, ary: [0; 4]};
+    assert_eq!(size_of::<Reorder4>(), 12);
+    assert!((&v.ary).as_ptr().is_aligned_to(4), "[u8; 4] should group with align-4 fields");
+    let v = Reorder2 {a: 0, b: 0, ary: [0; 6]};
+    assert_eq!(size_of::<Reorder2>(), 10);
+    assert!((&v.ary).as_ptr().is_aligned_to(2), "[u8; 6] should group with align-2 fields");
 }
diff --git a/src/test/ui/suggestions/borrow-for-loop-head.stderr b/src/test/ui/suggestions/borrow-for-loop-head.stderr
index 1059e3d1525..0cc8994fe1f 100644
--- a/src/test/ui/suggestions/borrow-for-loop-head.stderr
+++ b/src/test/ui/suggestions/borrow-for-loop-head.stderr
@@ -12,6 +12,7 @@ error[E0382]: use of moved value: `a`
 LL |     let a = vec![1, 2, 3];
    |         - move occurs because `a` has type `Vec<i32>`, which does not implement the `Copy` trait
 LL |     for i in &a {
+   |     ----------- inside of this loop
 LL |         for j in a {
    |                  ^ `a` moved due to this implicit call to `.into_iter()`, in previous iteration of loop
    |
diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
index 77cef485f30..918d37e6559 100644
--- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
+++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
@@ -78,20 +78,21 @@ LL | impl<P: Deref<Target: Unpin>> Pin<P> {
 error[E0308]: mismatched types
   --> $DIR/expected-boxed-future-isnt-pinned.rs:28:5
    |
-LL |   fn zap() -> BoxFuture<'static, i32> {
-   |               ----------------------- expected `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` because of return type
 LL | /     async {
 LL | |         42
 LL | |     }
-   | |_____^ expected struct `Pin`, found opaque type
-   |
-  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL |   pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |                                             ------------------------------- the found opaque type
-   |
-   = note:   expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
-           found opaque type `impl Future<Output = {integer}>`
+   | |     ^
+   | |     |
+   | |_____expected struct `Pin`, found `async` block
+   |       arguments to this function are incorrect
+   |
+   = note:     expected struct `Pin<Box<dyn Future<Output = i32> + Send>>`
+           found `async` block `impl Future<Output = {integer}>`
+note: function defined here
+  --> $SRC_DIR/core/src/future/mod.rs:LL:COL
+   |
+LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
+   |              ^^^^^^^^^^^^^^^
 help: you need to pin and box this expression
    |
 LL ~     Box::pin(async {
diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
index 597dc61c3f7..d0ddb34d9fe 100644
--- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
+++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
@@ -1,23 +1,3 @@
-error[E0423]: expected value, found struct variant `E::B`
-  --> $DIR/fn-or-tuple-struct-without-args.rs:36:16
-   |
-LL |     A(usize),
-   |     -------- similarly named tuple variant `A` defined here
-LL |     B { a: usize },
-   |     -------------- `E::B` defined here
-...
-LL |     let _: E = E::B;
-   |                ^^^^
-   |
-help: use struct literal syntax instead
-   |
-LL |     let _: E = E::B { a: val };
-   |                ~~~~~~~~~~~~~~~
-help: a tuple variant with a similar name exists
-   |
-LL |     let _: E = E::A;
-   |                   ~
-
 error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:29:20
    |
@@ -144,6 +124,12 @@ help: use parentheses to construct this tuple variant
 LL |     let _: E = E::A(/* usize */);
    |                    +++++++++++++
 
+error[E0533]: expected value, found struct variant `E::B`
+  --> $DIR/fn-or-tuple-struct-without-args.rs:36:16
+   |
+LL |     let _: E = E::B;
+   |                ^^^^ not a value
+
 error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:37:20
    |
@@ -293,5 +279,5 @@ LL |     let _: usize = closure();
 
 error: aborting due to 17 previous errors
 
-Some errors have detailed explanations: E0308, E0423, E0615.
+Some errors have detailed explanations: E0308, E0533, E0615.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/issue-84700.stderr b/src/test/ui/suggestions/issue-84700.stderr
index b36d8aba36d..ac9f5ab0b0c 100644
--- a/src/test/ui/suggestions/issue-84700.stderr
+++ b/src/test/ui/suggestions/issue-84700.stderr
@@ -7,15 +7,13 @@ LL |     Cow,
 LL |         FarmAnimal::Cow(_) => "moo".to_string(),
    |         ^^^^^^^^^^^^^^^^^^ help: use this syntax instead: `FarmAnimal::Cow`
 
-error[E0532]: expected tuple struct or tuple variant, found struct variant `FarmAnimal::Chicken`
+error[E0164]: expected tuple struct or tuple variant, found struct variant `FarmAnimal::Chicken`
   --> $DIR/issue-84700.rs:17:9
    |
-LL |     Chicken { num_eggs: usize },
-   |     --------------------------- `FarmAnimal::Chicken` defined here
-...
 LL |         FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(),
-   |         ^^^^^^^^^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `FarmAnimal::Chicken { num_eggs }`
+   |         ^^^^^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0532`.
+Some errors have detailed explanations: E0164, E0532.
+For more information about an error, try `rustc --explain E0164`.
diff --git a/src/test/ui/suggestions/ref-pattern-binding.fixed b/src/test/ui/suggestions/ref-pattern-binding.fixed
new file mode 100644
index 00000000000..c36040eeca3
--- /dev/null
+++ b/src/test/ui/suggestions/ref-pattern-binding.fixed
@@ -0,0 +1,19 @@
+// run-rustfix
+#![allow(unused)]
+
+struct S {
+    f: String,
+}
+
+fn main() {
+    let ref _moved @ ref _from = String::from("foo"); //~ ERROR
+    let ref _moved @ ref _from = String::from("foo"); //~ ERROR
+    let ref _moved @ ref _from = String::from("foo"); //~ ERROR
+    //~^ ERROR
+    let ref _moved @ ref _from = String::from("foo"); // ok
+    let ref _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR
+    let ref _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR
+    //~^ ERROR
+    let ref _moved @ S { ref f } = S { f: String::from("foo") }; // ok
+    let ref _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR
+}
diff --git a/src/test/ui/suggestions/ref-pattern-binding.rs b/src/test/ui/suggestions/ref-pattern-binding.rs
new file mode 100644
index 00000000000..c0d4feb0330
--- /dev/null
+++ b/src/test/ui/suggestions/ref-pattern-binding.rs
@@ -0,0 +1,19 @@
+// run-rustfix
+#![allow(unused)]
+
+struct S {
+    f: String,
+}
+
+fn main() {
+    let _moved @ _from = String::from("foo"); //~ ERROR
+    let _moved @ ref _from = String::from("foo"); //~ ERROR
+    let ref _moved @ _from = String::from("foo"); //~ ERROR
+    //~^ ERROR
+    let ref _moved @ ref _from = String::from("foo"); // ok
+    let _moved @ S { f } = S { f: String::from("foo") }; //~ ERROR
+    let ref _moved @ S { f } = S { f: String::from("foo") }; //~ ERROR
+    //~^ ERROR
+    let ref _moved @ S { ref f } = S { f: String::from("foo") }; // ok
+    let _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR
+}
diff --git a/src/test/ui/suggestions/ref-pattern-binding.stderr b/src/test/ui/suggestions/ref-pattern-binding.stderr
new file mode 100644
index 00000000000..10447ba7089
--- /dev/null
+++ b/src/test/ui/suggestions/ref-pattern-binding.stderr
@@ -0,0 +1,107 @@
+error: borrow of moved value
+  --> $DIR/ref-pattern-binding.rs:10:9
+   |
+LL |     let _moved @ ref _from = String::from("foo");
+   |         ------^^^---------
+   |         |        |
+   |         |        value borrowed here after move
+   |         value moved into `_moved` here
+   |         move occurs because `_moved` has type `String` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref _moved @ ref _from = String::from("foo");
+   |         +++
+
+error: cannot move out of value because it is borrowed
+  --> $DIR/ref-pattern-binding.rs:11:9
+   |
+LL |     let ref _moved @ _from = String::from("foo");
+   |         ----------^^^-----
+   |         |            |
+   |         |            value moved into `_from` here
+   |         value borrowed, by `_moved`, here
+
+error: cannot move out of value because it is borrowed
+  --> $DIR/ref-pattern-binding.rs:15:9
+   |
+LL |     let ref _moved @ S { f } = S { f: String::from("foo") };
+   |         ----------^^^^^^^-^^
+   |         |                |
+   |         |                value moved into `f` here
+   |         value borrowed, by `_moved`, here
+
+error: borrow of moved value
+  --> $DIR/ref-pattern-binding.rs:18:9
+   |
+LL |     let _moved @ S { ref f } = S { f: String::from("foo") };
+   |         ------^^^^^^^-----^^
+   |         |            |
+   |         |            value borrowed here after move
+   |         value moved into `_moved` here
+   |         move occurs because `_moved` has type `S` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref _moved @ S { ref f } = S { f: String::from("foo") };
+   |         +++
+
+error[E0382]: use of moved value
+  --> $DIR/ref-pattern-binding.rs:9:9
+   |
+LL |     let _moved @ _from = String::from("foo");
+   |         ^^^^^^   -----   ------------------- move occurs because value has type `String`, which does not implement the `Copy` trait
+   |         |        |
+   |         |        value moved here
+   |         value used here after move
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref _moved @ ref _from = String::from("foo");
+   |         +++          +++
+
+error[E0382]: borrow of moved value
+  --> $DIR/ref-pattern-binding.rs:11:9
+   |
+LL |     let ref _moved @ _from = String::from("foo");
+   |         ^^^^^^^^^^   -----   ------------------- move occurs because value has type `String`, which does not implement the `Copy` trait
+   |         |            |
+   |         |            value moved here
+   |         value borrowed here after move
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref _moved @ ref _from = String::from("foo");
+   |                      +++
+
+error[E0382]: use of partially moved value
+  --> $DIR/ref-pattern-binding.rs:14:9
+   |
+LL |     let _moved @ S { f } = S { f: String::from("foo") };
+   |         ^^^^^^       - value partially moved here
+   |         |
+   |         value used here after partial move
+   |
+   = note: partial move occurs because value has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref _moved @ S { ref f } = S { f: String::from("foo") };
+   |         +++              +++
+
+error[E0382]: borrow of partially moved value
+  --> $DIR/ref-pattern-binding.rs:15:9
+   |
+LL |     let ref _moved @ S { f } = S { f: String::from("foo") };
+   |         ^^^^^^^^^^       - value partially moved here
+   |         |
+   |         value borrowed here after partial move
+   |
+   = note: partial move occurs because value has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref _moved @ S { ref f } = S { f: String::from("foo") };
+   |                          +++
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/threads-sendsync/mpsc_stress.rs b/src/test/ui/threads-sendsync/mpsc_stress.rs
index a889542fec0..c2e1912deb7 100644
--- a/src/test/ui/threads-sendsync/mpsc_stress.rs
+++ b/src/test/ui/threads-sendsync/mpsc_stress.rs
@@ -64,9 +64,11 @@ fn shared_close_sender_does_not_lose_messages_iter() {
 
 #[test]
 fn shared_close_sender_does_not_lose_messages() {
-    for _ in 0..10000 {
-        shared_close_sender_does_not_lose_messages_iter();
-    }
+    with_minimum_timer_resolution(|| {
+        for _ in 0..10000 {
+            shared_close_sender_does_not_lose_messages_iter();
+        }
+    });
 }
 
 
@@ -96,17 +98,11 @@ fn concurrent_recv_timeout_and_upgrade_iter() {
 
 #[test]
 fn concurrent_recv_timeout_and_upgrade() {
-    // FIXME: fix and enable
-    if true { return }
-
-    // at the moment of writing this test fails like this:
-    // thread '<unnamed>' panicked at 'assertion failed: `(left == right)`
-    //  left: `4561387584`,
-    // right: `0`', libstd/sync/mpsc/shared.rs:253:13
-
-    for _ in 0..10000 {
-        concurrent_recv_timeout_and_upgrade_iter();
-    }
+    with_minimum_timer_resolution(|| {
+        for _ in 0..10000 {
+            concurrent_recv_timeout_and_upgrade_iter();
+        }
+    });
 }
 
 
@@ -159,7 +155,46 @@ fn concurrent_writes_iter() {
 
 #[test]
 fn concurrent_writes() {
-    for _ in 0..100 {
-        concurrent_writes_iter();
+    with_minimum_timer_resolution(|| {
+        for _ in 0..100 {
+            concurrent_writes_iter();
+        }
+    });
+}
+
+#[cfg(windows)]
+pub mod timeapi {
+    #![allow(non_snake_case)]
+    use std::ffi::c_uint;
+
+    pub const TIMERR_NOERROR: c_uint = 0;
+
+    #[link(name = "winmm")]
+    extern "system" {
+        pub fn timeBeginPeriod(uPeriod: c_uint) -> c_uint;
+        pub fn timeEndPeriod(uPeriod: c_uint) -> c_uint;
+    }
+}
+
+/// Window's minimum sleep time can be as much as 16ms.
+// This function evaluates the closure with this resolution
+// set as low as possible.
+///
+/// This takes the above test's duration from 10000*16/1000/60=2.67 minutes to ~16 seconds.
+fn with_minimum_timer_resolution(f: impl Fn()) {
+    #[cfg(windows)]
+    unsafe {
+        let ret = timeapi::timeBeginPeriod(1);
+        assert_eq!(ret, timeapi::TIMERR_NOERROR);
+
+        f();
+
+        let ret = timeapi::timeEndPeriod(1);
+        assert_eq!(ret, timeapi::TIMERR_NOERROR);
+    }
+
+    #[cfg(not(windows))]
+    {
+        f();
     }
 }
diff --git a/src/test/ui/track-diagnostics/track2.stderr b/src/test/ui/track-diagnostics/track2.stderr
index 38a621da816..fe13e5ef3f5 100644
--- a/src/test/ui/track-diagnostics/track2.stderr
+++ b/src/test/ui/track-diagnostics/track2.stderr
@@ -7,6 +7,11 @@ LL |     let _moved @ _from = String::from("foo");
    |         |        value moved here
    |         value used here after move
 -Ztrack-diagnostics: created at compiler/rustc_borrowck/src/borrowck_errors.rs:LL:CC
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     let ref _moved @ ref _from = String::from("foo");
+   |         +++          +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/alias/issue-83613.rs b/src/test/ui/traits/alias/issue-83613.rs
index 04320e72076..2462e703a71 100644
--- a/src/test/ui/traits/alias/issue-83613.rs
+++ b/src/test/ui/traits/alias/issue-83613.rs
@@ -9,5 +9,4 @@ trait AnotherTrait {}
 impl<T: Send> AnotherTrait for T {}
 impl AnotherTrait for OpaqueType {}
 //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
-//~| ERROR cannot implement trait on type alias impl trait
 fn main() {}
diff --git a/src/test/ui/traits/alias/issue-83613.stderr b/src/test/ui/traits/alias/issue-83613.stderr
index b9d93160192..a78294da6c1 100644
--- a/src/test/ui/traits/alias/issue-83613.stderr
+++ b/src/test/ui/traits/alias/issue-83613.stderr
@@ -6,18 +6,6 @@ LL | impl<T: Send> AnotherTrait for T {}
 LL | impl AnotherTrait for OpaqueType {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
 
-error: cannot implement trait on type alias impl trait
-  --> $DIR/issue-83613.rs:10:23
-   |
-LL | impl AnotherTrait for OpaqueType {}
-   |                       ^^^^^^^^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/issue-83613.rs:4:19
-   |
-LL | type OpaqueType = impl OpaqueTrait;
-   |                   ^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/predicate_can_apply-hang.rs b/src/test/ui/traits/predicate_can_apply-hang.rs
new file mode 100644
index 00000000000..5f01645da52
--- /dev/null
+++ b/src/test/ui/traits/predicate_can_apply-hang.rs
@@ -0,0 +1,6 @@
+fn f<B>(x: Vec<[[[B; 1]; 1]; 1]>) -> impl PartialEq<B> {
+    //~^ ERROR can't compare `Vec<[[[B; 1]; 1]; 1]>` with `B`
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/predicate_can_apply-hang.stderr b/src/test/ui/traits/predicate_can_apply-hang.stderr
new file mode 100644
index 00000000000..49fe63b412a
--- /dev/null
+++ b/src/test/ui/traits/predicate_can_apply-hang.stderr
@@ -0,0 +1,21 @@
+error[E0277]: can't compare `Vec<[[[B; 1]; 1]; 1]>` with `B`
+  --> $DIR/predicate_can_apply-hang.rs:1:38
+   |
+LL | fn f<B>(x: Vec<[[[B; 1]; 1]; 1]>) -> impl PartialEq<B> {
+   |                                      ^^^^^^^^^^^^^^^^^ no implementation for `Vec<[[[B; 1]; 1]; 1]> == B`
+LL |
+LL |     x
+   |     - return type was inferred to be `Vec<[[[B; 1]; 1]; 1]>` here
+   |
+   = help: the trait `PartialEq<B>` is not implemented for `Vec<[[[B; 1]; 1]; 1]>`
+   = help: the following other types implement trait `PartialEq<Rhs>`:
+             <Vec<T, A1> as PartialEq<Vec<U, A2>>>
+             <Vec<T, A> as PartialEq<&[U; N]>>
+             <Vec<T, A> as PartialEq<&[U]>>
+             <Vec<T, A> as PartialEq<&mut [U]>>
+             <Vec<T, A> as PartialEq<[U; N]>>
+             <Vec<T, A> as PartialEq<[U]>>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs
index 5f5a2574bab..d624187561e 100644
--- a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs
+++ b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs
@@ -7,7 +7,11 @@ use core::ops::Deref;
 // issue 89190
 trait A {}
 trait B: A {}
+
 impl<'a> Deref for dyn 'a + B {
+    //~^ ERROR `(dyn B + 'a)` implements `Deref` with supertrait `A` as target
+    //~| WARN this was previously accepted by the compiler but is being phased out;
+
     type Target = dyn A;
     fn deref(&self) -> &Self::Target {
         todo!()
@@ -18,8 +22,6 @@ fn take_a(_: &dyn A) {}
 
 fn whoops(b: &dyn B) {
     take_a(b)
-    //~^ ERROR `dyn B` implements `Deref` with supertrait `A` as output
-    //~^^ WARN this was previously accepted by the compiler but is being phased out;
 }
 
 fn main() {}
diff --git a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr
index 41381a3ffd1..4533b116342 100644
--- a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr
+++ b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr
@@ -1,8 +1,11 @@
-error: `dyn B` implements `Deref` with supertrait `A` as output
-  --> $DIR/migrate-lint-deny.rs:20:12
+error: `(dyn B + 'a)` implements `Deref` with supertrait `A` as target
+  --> $DIR/migrate-lint-deny.rs:11:1
    |
-LL |     take_a(b)
-   |            ^
+LL | impl<'a> Deref for dyn 'a + B {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     type Target = dyn A;
+   |     -------------------- target type is set here
    |
    = 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 #89460 <https://github.com/rust-lang/rust/issues/89460>
diff --git a/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr b/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr
index c9f2a3ed9f4..f738b03eed6 100644
--- a/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr
+++ b/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr
@@ -23,6 +23,10 @@ LL |         println!("{}", x);
    |                        ^ value borrowed here after move
    |
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |             ::std::mem::drop(x.clone());
+   |                               ++++++++
 
 error[E0506]: cannot assign to `i` because it is borrowed
   --> $DIR/try-block-maybe-bad-lifetime.rs:40:9
diff --git a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr
index 15d15f2f40d..6870b9d7d09 100644
--- a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr
+++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr
@@ -2,7 +2,7 @@ error[E0533]: expected unit struct, unit variant or constant, found tuple varian
   --> $DIR/incorrect-variant-form-through-Self-issue-58006.rs:8:13
    |
 LL |             Self::A => (),
-   |             ^^^^^^^
+   |             ^^^^^^^ not a unit struct, unit variant or constant
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs
index e4abb96b4bf..5ed7988e4da 100644
--- a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs
+++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs
@@ -6,7 +6,7 @@ type Alias = Enum;
 
 fn main() {
     Alias::Braced;
-    //~^ ERROR expected unit struct, unit variant or constant, found struct variant `Alias::Braced` [E0533]
+    //~^ ERROR expected value, found struct variant `Alias::Braced` [E0533]
     let Alias::Braced = panic!();
     //~^ ERROR expected unit struct, unit variant or constant, found struct variant `Alias::Braced` [E0533]
     let Alias::Braced(..) = panic!();
diff --git a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr
index 8f3180a8639..c9ac99ede6f 100644
--- a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr
+++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr
@@ -1,20 +1,20 @@
-error[E0533]: expected unit struct, unit variant or constant, found struct variant `Alias::Braced`
+error[E0533]: expected value, found struct variant `Alias::Braced`
   --> $DIR/incorrect-variant-form-through-alias-caught.rs:8:5
    |
 LL |     Alias::Braced;
-   |     ^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^ not a value
 
 error[E0533]: expected unit struct, unit variant or constant, found struct variant `Alias::Braced`
   --> $DIR/incorrect-variant-form-through-alias-caught.rs:10:9
    |
 LL |     let Alias::Braced = panic!();
-   |         ^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^ not a unit struct, unit variant or constant
 
 error[E0164]: expected tuple struct or tuple variant, found struct variant `Alias::Braced`
   --> $DIR/incorrect-variant-form-through-alias-caught.rs:12:9
    |
 LL |     let Alias::Braced(..) = panic!();
-   |         ^^^^^^^^^^^^^^^^^ not a tuple variant or struct
+   |         ^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
 
 error[E0618]: expected function, found enum variant `Alias::Unit`
   --> $DIR/incorrect-variant-form-through-alias-caught.rs:15:5
@@ -37,7 +37,7 @@ error[E0164]: expected tuple struct or tuple variant, found unit variant `Alias:
   --> $DIR/incorrect-variant-form-through-alias-caught.rs:17:9
    |
 LL |     let Alias::Unit() = panic!();
-   |         ^^^^^^^^^^^^^ not a tuple variant or struct
+   |         ^^^^^^^^^^^^^ not a tuple struct or tuple variant
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/coherence.rs b/src/test/ui/type-alias-impl-trait/coherence.rs
index 98ac215ad6c..077a31494a9 100644
--- a/src/test/ui/type-alias-impl-trait/coherence.rs
+++ b/src/test/ui/type-alias-impl-trait/coherence.rs
@@ -12,6 +12,6 @@ fn use_alias<T>(val: T) -> AliasOfForeignType<T> {
 }
 
 impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {}
-//~^ ERROR cannot implement trait on type alias impl trait
+//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
 
 fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/coherence.stderr b/src/test/ui/type-alias-impl-trait/coherence.stderr
index 3ce25d94f6e..c923eb08ab3 100644
--- a/src/test/ui/type-alias-impl-trait/coherence.stderr
+++ b/src/test/ui/type-alias-impl-trait/coherence.stderr
@@ -1,14 +1,14 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/coherence.rs:14:41
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence.rs:14:1
    |
 LL | impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {}
-   |                                         ^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------
+   | |                                       |
+   | |                                       `AliasOfForeignType<T>` is not defined in the current crate
+   | impl doesn't use only types from inside the current crate
    |
-note: type alias impl trait defined here
-  --> $DIR/coherence.rs:9:30
-   |
-LL | type AliasOfForeignType<T> = impl LocalTrait;
-   |                              ^^^^^^^^^^^^^^^
+   = note: define and implement a trait or new type instead
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/type-alias-impl-trait/coherence_generalization.rs b/src/test/ui/type-alias-impl-trait/coherence_generalization.rs
new file mode 100644
index 00000000000..5c9ad9498b6
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/coherence_generalization.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+trait Trait {}
+type Opaque<T> = impl Sized;
+fn foo<T>() -> Opaque<T> {
+    ()
+}
+
+impl<T, V> Trait for (T, V, V, u32) {}
+impl<U, V> Trait for (Opaque<U>, V, i32, V) {}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs b/src/test/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs
new file mode 100644
index 00000000000..0efbd1c2bd5
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+trait Foo {
+    type Assoc;
+}
+
+impl Foo for i32 {
+    type Assoc = u32;
+}
+type ImplTrait = impl Sized;
+fn constrain() -> ImplTrait {
+    1u64
+}
+impl Foo for i64 {
+    type Assoc = ImplTrait;
+}
+
+trait Bar<T> {}
+
+impl<T: Foo> Bar<<T as Foo>::Assoc> for T {}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs b/src/test/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs
new file mode 100644
index 00000000000..3f1a9d12b44
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs
@@ -0,0 +1,33 @@
+#![feature(type_alias_impl_trait)]
+
+trait Foo {}
+impl Foo for () {}
+impl Foo for i32 {}
+
+type Bar<T: Foo> = impl std::fmt::Debug;
+fn defining_use<T: Foo>() -> Bar<T> {
+    42
+}
+
+trait Bop {}
+
+impl Bop for Bar<()> {}
+
+// If the hidden type is the same, this is effectively a second impl for the same type.
+impl Bop for Bar<i32> {}
+//~^ ERROR conflicting implementations
+
+type Barr = impl std::fmt::Debug;
+fn defining_use2() -> Barr {
+    42
+}
+
+// Even completely different opaque types must conflict.
+impl Bop for Barr {}
+//~^ ERROR conflicting implementations
+
+// And obviously the hidden type must conflict, too.
+impl Bop for i32 {}
+//~^ ERROR conflicting implementations
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr b/src/test/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr
new file mode 100644
index 00000000000..aaf75cc3db9
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr
@@ -0,0 +1,30 @@
+error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>`
+  --> $DIR/impl_trait_for_same_tait.rs:17:1
+   |
+LL | impl Bop for Bar<()> {}
+   | -------------------- first implementation here
+...
+LL | impl Bop for Bar<i32> {}
+   | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>`
+
+error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>`
+  --> $DIR/impl_trait_for_same_tait.rs:26:1
+   |
+LL | impl Bop for Bar<()> {}
+   | -------------------- first implementation here
+...
+LL | impl Bop for Barr {}
+   | ^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>`
+
+error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>`
+  --> $DIR/impl_trait_for_same_tait.rs:30:1
+   |
+LL | impl Bop for Bar<()> {}
+   | -------------------- first implementation here
+...
+LL | impl Bop for i32 {}
+   | ^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait.rs b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait.rs
new file mode 100644
index 00000000000..9f32c5d888b
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait.rs
@@ -0,0 +1,21 @@
+// compile-flags: --crate-type=lib
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+type Alias = impl Sized;
+
+fn constrain() -> Alias {
+    1i32
+}
+
+trait HideIt {
+    type Assoc;
+}
+
+impl HideIt for () {
+    type Assoc = Alias;
+}
+
+pub trait Yay {}
+
+impl Yay for <() as HideIt>::Assoc {}
diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs
new file mode 100644
index 00000000000..8ec20acef4d
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs
@@ -0,0 +1,19 @@
+#![feature(type_alias_impl_trait)]
+
+use std::fmt::Debug;
+
+type Foo = impl Debug;
+pub trait Yay { }
+impl Yay for Foo { }
+
+fn foo() {
+    is_yay::<u32>();   //~ ERROR: the trait bound `u32: Yay` is not satisfied
+    is_debug::<u32>(); // OK
+    is_yay::<Foo>();   // OK
+    is_debug::<Foo>(); // OK
+}
+
+fn is_yay<T: Yay>() { }
+fn is_debug<T: Debug>() { }
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr
new file mode 100644
index 00000000000..1c83105a18a
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `u32: Yay` is not satisfied
+  --> $DIR/impl_trait_for_tait_bound.rs:10:14
+   |
+LL |     is_yay::<u32>();
+   |              ^^^ the trait `Yay` is not implemented for `u32`
+   |
+   = help: the trait `Yay` is implemented for `Foo`
+note: required by a bound in `is_yay`
+  --> $DIR/impl_trait_for_tait_bound.rs:16:14
+   |
+LL | fn is_yay<T: Yay>() { }
+   |              ^^^ required by this bound in `is_yay`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs
new file mode 100644
index 00000000000..a4b8c2d190d
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs
@@ -0,0 +1,16 @@
+#![feature(type_alias_impl_trait)]
+
+use std::fmt::Debug;
+
+type Foo = impl Debug;
+
+pub trait Yay { }
+impl Yay for u32 { }
+
+fn foo() {
+    is_yay::<Foo>(); //~ ERROR: the trait bound `Foo: Yay` is not satisfied
+}
+
+fn is_yay<T: Yay>() { }
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr
new file mode 100644
index 00000000000..a6440f02c27
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `Foo: Yay` is not satisfied
+  --> $DIR/impl_trait_for_tait_bound2.rs:11:14
+   |
+LL |     is_yay::<Foo>();
+   |              ^^^ the trait `Yay` is not implemented for `Foo`
+   |
+   = help: the trait `Yay` is implemented for `u32`
+note: required by a bound in `is_yay`
+  --> $DIR/impl_trait_for_tait_bound2.rs:14:14
+   |
+LL | fn is_yay<T: Yay>() { }
+   |              ^^^ required by this bound in `is_yay`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-65384.rs b/src/test/ui/type-alias-impl-trait/issue-65384.rs
index 9a119c4d2e0..9a9b2269f80 100644
--- a/src/test/ui/type-alias-impl-trait/issue-65384.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-65384.rs
@@ -8,7 +8,7 @@ impl MyTrait for () {}
 type Bar = impl MyTrait;
 
 impl MyTrait for Bar {}
-//~^ ERROR: cannot implement trait on type alias impl trait
+//~^ ERROR: conflicting implementations of trait `MyTrait` for type `()`
 
 fn bazr() -> Bar { }
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-65384.stderr b/src/test/ui/type-alias-impl-trait/issue-65384.stderr
index 41bcea27e1f..f6692ae3207 100644
--- a/src/test/ui/type-alias-impl-trait/issue-65384.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-65384.stderr
@@ -1,14 +1,12 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/issue-65384.rs:10:18
+error[E0119]: conflicting implementations of trait `MyTrait` for type `()`
+  --> $DIR/issue-65384.rs:10:1
    |
+LL | impl MyTrait for () {}
+   | ------------------- first implementation here
+...
 LL | impl MyTrait for Bar {}
-   |                  ^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/issue-65384.rs:8:12
-   |
-LL | type Bar = impl MyTrait;
-   |            ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs b/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs
index fb56cc54d63..b97e444c6d0 100644
--- a/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs
@@ -1,6 +1,8 @@
 // Regression test for issue #76202
 // Tests that we don't ICE when we have a trait impl on a TAIT.
 
+// check-pass
+
 #![feature(type_alias_impl_trait)]
 
 trait Dummy {}
@@ -14,7 +16,12 @@ trait Test {
 }
 
 impl Test for F {
-    //~^ ERROR cannot implement trait
+    fn test(self) {}
+}
+
+// Ok because `i32` does not implement `Dummy`,
+// so it can't possibly be the hidden type of `F`.
+impl Test for i32 {
     fn test(self) {}
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.stderr b/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.stderr
deleted file mode 100644
index 2d4a6854a92..00000000000
--- a/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/issue-76202-trait-impl-for-tait.rs:16:15
-   |
-LL | impl Test for F {
-   |               ^
-   |
-note: type alias impl trait defined here
-  --> $DIR/issue-76202-trait-impl-for-tait.rs:9:10
-   |
-LL | type F = impl Dummy;
-   |          ^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs b/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs
index fa25d8f762e..2ba4befea2a 100644
--- a/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs
@@ -1,6 +1,8 @@
 // Regression test for issues #84660 and #86411: both are variations on #76202.
 // Tests that we don't ICE when we have an opaque type appearing anywhere in an impl header.
 
+// check-pass
+
 #![feature(type_alias_impl_trait)]
 
 trait Foo {}
@@ -12,7 +14,7 @@ trait TraitArg<T> {
     fn f();
 }
 
-impl TraitArg<Bar> for () { //~ ERROR cannot implement trait
+impl TraitArg<Bar> for () {
     fn f() {
         println!("ho");
     }
diff --git a/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.stderr b/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.stderr
deleted file mode 100644
index bb70d07be59..00000000000
--- a/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/issue-84660-trait-impl-for-tait.rs:15:15
-   |
-LL | impl TraitArg<Bar> for () {
-   |               ^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/issue-84660-trait-impl-for-tait.rs:8:12
-   |
-LL | type Bar = impl Foo;
-   |            ^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
index f12d1b6d953..48d4b0c96ff 100644
--- a/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
@@ -13,14 +13,14 @@ trait Trait<T, In> {
     fn convert(i: In) -> Self::Out;
 }
 
-impl<In, Out> Trait<Bar, In> for Out { //~ ERROR cannot implement trait
+impl<In, Out> Trait<Bar, In> for Out {
     type Out = Out;
     fn convert(_i: In) -> Self::Out {
         unreachable!();
     }
 }
 
-impl<In, Out> Trait<(), In> for Out {
+impl<In, Out> Trait<(), In> for Out { //~ ERROR conflicting implementations of trait `Trait<Bar, _>`
     type Out = In;
     fn convert(i: In) -> Self::Out {
         i
diff --git a/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr
index f2d600fb46c..6a75e1bd2c0 100644
--- a/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr
@@ -1,14 +1,12 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/issue-84660-unsoundness.rs:16:21
+error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
+  --> $DIR/issue-84660-unsoundness.rs:23:1
    |
 LL | impl<In, Out> Trait<Bar, In> for Out {
-   |                     ^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/issue-84660-unsoundness.rs:8:12
-   |
-LL | type Bar = impl Foo;
-   |            ^^^^^^^^
+   | ------------------------------------ first implementation here
+...
+LL | impl<In, Out> Trait<(), In> for Out {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs
index ebf3a99bbf9..b0ebdd1bfab 100644
--- a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs
+++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs
@@ -4,11 +4,11 @@
 use std::fmt::Debug;
 
 type FooX = impl Debug;
+//~^ ERROR unconstrained opaque type
 
 trait Foo<A> { }
 
 impl Foo<FooX> for () { }
-//~^ cannot implement trait on type alias impl trait
 
 fn foo() -> impl Foo<FooX> {
     ()
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr
index 4a3fb16733e..b1d947a9ccf 100644
--- a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr
+++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr
@@ -1,14 +1,10 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/nested-tait-inference3.rs:10:10
-   |
-LL | impl Foo<FooX> for () { }
-   |          ^^^^
-   |
-note: type alias impl trait defined here
+error: unconstrained opaque type
   --> $DIR/nested-tait-inference3.rs:6:13
    |
 LL | type FooX = impl Debug;
    |             ^^^^^^^^^^
+   |
+   = note: `FooX` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/hang-in-overflow.rs b/src/test/ui/typeck/hang-in-overflow.rs
new file mode 100644
index 00000000000..a8330c9b65c
--- /dev/null
+++ b/src/test/ui/typeck/hang-in-overflow.rs
@@ -0,0 +1,19 @@
+// normalize-stderr-test "the requirement `.*`" -> "the requirement `...`"
+// normalize-stderr-test "required for `.*` to implement `.*`" -> "required for `...` to implement `...`"
+// normalize-stderr-test: ".*the full type name has been written to.*\n" -> ""
+
+// Currently this fatally aborts instead of hanging.
+// Make sure at least that this doesn't turn into a hang.
+
+fn f() {
+    foo::<_>();
+    //~^ ERROR overflow evaluating the requirement
+}
+
+fn foo<B>()
+where
+    Vec<[[[B; 1]; 1]; 1]>: PartialEq<B>,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/hang-in-overflow.stderr b/src/test/ui/typeck/hang-in-overflow.stderr
new file mode 100644
index 00000000000..7a7b85b19b4
--- /dev/null
+++ b/src/test/ui/typeck/hang-in-overflow.stderr
@@ -0,0 +1,22 @@
+error[E0275]: overflow evaluating the requirement `...`
+  --> $DIR/hang-in-overflow.rs:9:5
+   |
+LL |     foo::<_>();
+   |     ^^^^^^^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`hang_in_overflow`)
+   = note: required for `...` to implement `...`
+   = note: 127 redundant requirements hidden
+   = note: required for `...` to implement `...`
+note: required by a bound in `foo`
+  --> $DIR/hang-in-overflow.rs:15:28
+   |
+LL | fn foo<B>()
+   |    --- required by a bound in this
+LL | where
+LL |     Vec<[[[B; 1]; 1]; 1]>: PartialEq<B>,
+   |                            ^^^^^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/typeck/issue-104513-ice.rs b/src/test/ui/typeck/issue-104513-ice.rs
new file mode 100644
index 00000000000..bcac0fa1e70
--- /dev/null
+++ b/src/test/ui/typeck/issue-104513-ice.rs
@@ -0,0 +1,6 @@
+struct S;
+fn f() {
+    let _: S<impl Oops> = S; //~ ERROR cannot find trait `Oops` in this scope
+    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+}
+fn main() {}
diff --git a/src/test/ui/typeck/issue-104513-ice.stderr b/src/test/ui/typeck/issue-104513-ice.stderr
new file mode 100644
index 00000000000..2b3b1b9efdf
--- /dev/null
+++ b/src/test/ui/typeck/issue-104513-ice.stderr
@@ -0,0 +1,18 @@
+error[E0405]: cannot find trait `Oops` in this scope
+  --> $DIR/issue-104513-ice.rs:3:19
+   |
+LL | fn f() {
+   |     - help: you might be missing a type parameter: `<Oops>`
+LL |     let _: S<impl Oops> = S;
+   |                   ^^^^ not found in this scope
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+  --> $DIR/issue-104513-ice.rs:3:14
+   |
+LL |     let _: S<impl Oops> = S;
+   |              ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0405, E0562.
+For more information about an error, try `rustc --explain E0405`.
diff --git a/src/test/ui/union/union-move.mirunsafeck.stderr b/src/test/ui/union/union-move.mirunsafeck.stderr
index 53050cf539e..6381ae874ba 100644
--- a/src/test/ui/union/union-move.mirunsafeck.stderr
+++ b/src/test/ui/union/union-move.mirunsafeck.stderr
@@ -8,6 +8,14 @@ LL |         move_out(x.f1_nocopy);
    |                  ----------- value moved here
 LL |         move_out(x.f2_nocopy);
    |                  ^^^^^^^^^^^ value used here after move
+   |
+note: consider changing this parameter type in function `move_out` to borrow instead if owning the value isn't necessary
+  --> $DIR/union-move.rs:10:19
+   |
+LL | fn move_out<T>(x: T) {}
+   |    --------       ^ this parameter takes ownership of the value
+   |    |
+   |    in this function
 
 error[E0382]: use of moved value: `x`
   --> $DIR/union-move.rs:45:18
@@ -19,6 +27,14 @@ LL |         move_out(x.f2_nocopy);
    |                  ----------- value moved here
 LL |         move_out(x.f3_copy);
    |                  ^^^^^^^^^ value used here after move
+   |
+note: consider changing this parameter type in function `move_out` to borrow instead if owning the value isn't necessary
+  --> $DIR/union-move.rs:10:19
+   |
+LL | fn move_out<T>(x: T) {}
+   |    --------       ^ this parameter takes ownership of the value
+   |    |
+   |    in this function
 
 error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
   --> $DIR/union-move.rs:52:18
diff --git a/src/test/ui/union/union-move.thirunsafeck.stderr b/src/test/ui/union/union-move.thirunsafeck.stderr
index 53050cf539e..6381ae874ba 100644
--- a/src/test/ui/union/union-move.thirunsafeck.stderr
+++ b/src/test/ui/union/union-move.thirunsafeck.stderr
@@ -8,6 +8,14 @@ LL |         move_out(x.f1_nocopy);
    |                  ----------- value moved here
 LL |         move_out(x.f2_nocopy);
    |                  ^^^^^^^^^^^ value used here after move
+   |
+note: consider changing this parameter type in function `move_out` to borrow instead if owning the value isn't necessary
+  --> $DIR/union-move.rs:10:19
+   |
+LL | fn move_out<T>(x: T) {}
+   |    --------       ^ this parameter takes ownership of the value
+   |    |
+   |    in this function
 
 error[E0382]: use of moved value: `x`
   --> $DIR/union-move.rs:45:18
@@ -19,6 +27,14 @@ LL |         move_out(x.f2_nocopy);
    |                  ----------- value moved here
 LL |         move_out(x.f3_copy);
    |                  ^^^^^^^^^ value used here after move
+   |
+note: consider changing this parameter type in function `move_out` to borrow instead if owning the value isn't necessary
+  --> $DIR/union-move.rs:10:19
+   |
+LL | fn move_out<T>(x: T) {}
+   |    --------       ^ this parameter takes ownership of the value
+   |    |
+   |    in this function
 
 error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
   --> $DIR/union-move.rs:52:18
diff --git a/src/test/ui/unop-move-semantics.stderr b/src/test/ui/unop-move-semantics.stderr
index 65d866c716e..d52a92b8888 100644
--- a/src/test/ui/unop-move-semantics.stderr
+++ b/src/test/ui/unop-move-semantics.stderr
@@ -14,6 +14,10 @@ note: calling this operator moves the left-hand side
    |
 LL |     fn not(self) -> Self::Output;
    |            ^^^^
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     !x.clone();
+   |       ++++++++
 help: consider further restricting this bound
    |
 LL | fn move_then_borrow<T: Not<Output=T> + Clone + Copy>(x: T) {
diff --git a/src/test/ui/unsized-locals/borrow-after-move.stderr b/src/test/ui/unsized-locals/borrow-after-move.stderr
index 28ae1c0688c..d8bffd4f9cf 100644
--- a/src/test/ui/unsized-locals/borrow-after-move.stderr
+++ b/src/test/ui/unsized-locals/borrow-after-move.stderr
@@ -28,6 +28,14 @@ LL |         drop_unsized(y);
 ...
 LL |         println!("{}", &y);
    |                        ^^ value borrowed here after move
+   |
+note: consider changing this parameter type in function `drop_unsized` to borrow instead if owning the value isn't necessary
+  --> $DIR/borrow-after-move.rs:14:31
+   |
+LL | fn drop_unsized<T: ?Sized>(_: T) {}
+   |    ------------               ^ this parameter takes ownership of the value
+   |    |
+   |    in this function
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/borrow-after-move.rs:31:24
@@ -66,6 +74,11 @@ LL |         x.foo();
    |         - value moved here
 LL |         println!("{}", &x);
    |                        ^^ value borrowed here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         x.clone().foo();
+   |          ++++++++
 
 error: aborting due to 5 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/unsized-locals/double-move.stderr b/src/test/ui/unsized-locals/double-move.stderr
index dfae6cc75d9..71534818141 100644
--- a/src/test/ui/unsized-locals/double-move.stderr
+++ b/src/test/ui/unsized-locals/double-move.stderr
@@ -16,6 +16,14 @@ LL |         drop_unsized(y);
    |                      - value moved here
 LL |         drop_unsized(y);
    |                      ^ value used here after move
+   |
+note: consider changing this parameter type in function `drop_unsized` to borrow instead if owning the value isn't necessary
+  --> $DIR/double-move.rs:14:31
+   |
+LL | fn drop_unsized<T: ?Sized>(_: T) {}
+   |    ------------               ^ this parameter takes ownership of the value
+   |    |
+   |    in this function
 
 error[E0382]: use of moved value: `x`
   --> $DIR/double-move.rs:27:22
diff --git a/src/test/ui/use/use-after-move-based-on-type.stderr b/src/test/ui/use/use-after-move-based-on-type.stderr
index 445f14d65e3..7b4d2454994 100644
--- a/src/test/ui/use/use-after-move-based-on-type.stderr
+++ b/src/test/ui/use/use-after-move-based-on-type.stderr
@@ -9,6 +9,10 @@ LL |     println!("{}", x);
    |                    ^ value borrowed here after move
    |
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _y = x.clone();
+   |               ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/use/use-after-move-implicity-coerced-object.stderr b/src/test/ui/use/use-after-move-implicity-coerced-object.stderr
index 26804216d9d..dfa0c04836e 100644
--- a/src/test/ui/use/use-after-move-implicity-coerced-object.stderr
+++ b/src/test/ui/use/use-after-move-implicity-coerced-object.stderr
@@ -9,6 +9,14 @@ LL |     l.push(n);
 LL |
 LL |     let x = n.to_string();
    |             ^^^^^^^^^^^^^ value borrowed here after move
+   |
+note: consider changing this parameter type in method `push` to borrow instead if owning the value isn't necessary
+  --> $DIR/use-after-move-implicity-coerced-object.rs:17:27
+   |
+LL |     fn push(&mut self, n: Box<dyn ToString + 'static>) {
+   |        ----               ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this parameter takes ownership of the value
+   |        |
+   |        in this method
 
 error: aborting due to previous error
 
diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs
index dde9745afb7..66e6982d6b4 100644
--- a/src/tools/build-manifest/src/versions.rs
+++ b/src/tools/build-manifest/src/versions.rs
@@ -49,10 +49,10 @@ pkg_type! {
     Cargo = "cargo",
     HtmlDocs = "rust-docs",
     RustAnalysis = "rust-analysis",
+    Clippy = "clippy",
+    Rustfmt = "rustfmt",
     Rls = "rls"; preview = true,
     RustAnalyzer = "rust-analyzer"; preview = true,
-    Clippy = "clippy"; preview = true,
-    Rustfmt = "rustfmt"; preview = true,
     LlvmTools = "llvm-tools"; preview = true,
     Miri = "miri"; preview = true,
     JsonDocs = "rust-docs-json"; preview = true,
diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs
index aa346daf7e5..388203ee463 100644
--- a/src/tools/bump-stage0/src/main.rs
+++ b/src/tools/bump-stage0/src/main.rs
@@ -6,7 +6,7 @@ use std::convert::TryInto;
 
 const PATH: &str = "src/stage0.json";
 const COMPILER_COMPONENTS: &[&str] = &["rustc", "rust-std", "cargo"];
-const RUSTFMT_COMPONENTS: &[&str] = &["rustfmt-preview"];
+const RUSTFMT_COMPONENTS: &[&str] = &["rustfmt"];
 
 struct Tool {
     config: Config,
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject eb5d35917b2395194593c9ca70c3778f60c1573
+Subproject ba607b23db8398723d659249d9abf5536bc322e
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 2d7bda27e4f..6f1f73c1fd2 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -4,13 +4,157 @@ All notable changes to this project will be documented in this file.
 See [Changelog Update](book/src/development/infrastructure/changelog_update.md) if you want to update this
 document.
 
-## Unreleased / In Rust Nightly
+## Unreleased / Beta / In Rust Nightly
 
-[3c7e7dbc...master](https://github.com/rust-lang/rust-clippy/compare/3c7e7dbc...master)
+[b52fb523...master](https://github.com/rust-lang/rust-clippy/compare/b52fb523...master)
+
+## Rust 1.65
+
+Current stable, released 2022-11-03
+
+[3c7e7dbc...b52fb523](https://github.com/rust-lang/rust-clippy/compare/3c7e7dbc...b52fb523)
+
+### Important Changes
+
+* Clippy now has an `--explain <LINT>` command to show the lint description in the console
+  [#8952](https://github.com/rust-lang/rust-clippy/pull/8952)
+
+### New Lints
+
+* [`unused_peekable`]
+  [#9258](https://github.com/rust-lang/rust-clippy/pull/9258)
+* [`collapsible_str_replace`]
+  [#9269](https://github.com/rust-lang/rust-clippy/pull/9269)
+* [`manual_string_new`]
+  [#9295](https://github.com/rust-lang/rust-clippy/pull/9295)
+* [`iter_on_empty_collections`]
+  [#9187](https://github.com/rust-lang/rust-clippy/pull/9187)
+* [`iter_on_single_items`]
+  [#9187](https://github.com/rust-lang/rust-clippy/pull/9187)
+* [`bool_to_int_with_if`]
+  [#9412](https://github.com/rust-lang/rust-clippy/pull/9412)
+* [`multi_assignments`]
+  [#9379](https://github.com/rust-lang/rust-clippy/pull/9379)
+* [`result_large_err`]
+  [#9373](https://github.com/rust-lang/rust-clippy/pull/9373)
+* [`partialeq_to_none`]
+  [#9288](https://github.com/rust-lang/rust-clippy/pull/9288)
+* [`suspicious_to_owned`]
+  [#8984](https://github.com/rust-lang/rust-clippy/pull/8984)
+* [`cast_slice_from_raw_parts`]
+  [#9247](https://github.com/rust-lang/rust-clippy/pull/9247)
+* [`manual_instant_elapsed`]
+  [#9264](https://github.com/rust-lang/rust-clippy/pull/9264)
+
+### Moves and Deprecations
+
+* Moved [`significant_drop_in_scrutinee`] to `nursery` (now allow-by-default)
+  [#9302](https://github.com/rust-lang/rust-clippy/pull/9302)
+* Rename `logic_bug` to [`overly_complex_bool_expr`]
+  [#9306](https://github.com/rust-lang/rust-clippy/pull/9306)
+* Rename `arithmetic` to [`arithmetic_side_effects`]
+  [#9443](https://github.com/rust-lang/rust-clippy/pull/9443)
+* Moved [`only_used_in_recursion`] to complexity (now warn-by-default)
+  [#8804](https://github.com/rust-lang/rust-clippy/pull/8804)
+* Moved [`assertions_on_result_states`] to restriction (now allow-by-default)
+  [#9273](https://github.com/rust-lang/rust-clippy/pull/9273)
+* Renamed `blacklisted_name` to [`disallowed_names`]
+  [#8974](https://github.com/rust-lang/rust-clippy/pull/8974)
+
+### Enhancements
+
+* [`option_if_let_else`]: Now also checks for match expressions
+  [#8696](https://github.com/rust-lang/rust-clippy/pull/8696)
+* [`explicit_auto_deref`]: Now lints on implicit returns in closures
+  [#9126](https://github.com/rust-lang/rust-clippy/pull/9126)
+* [`needless_borrow`]: Now considers trait implementations
+  [#9136](https://github.com/rust-lang/rust-clippy/pull/9136)
+* [`suboptimal_flops`], [`imprecise_flops`]: Now lint on constant expressions
+  [#9404](https://github.com/rust-lang/rust-clippy/pull/9404)
+* [`if_let_mutex`]: Now detects mutex behind references and warns about deadlocks
+  [#9318](https://github.com/rust-lang/rust-clippy/pull/9318)
+
+### False Positive Fixes
+
+* [`unit_arg`] [`default_trait_access`] [`missing_docs_in_private_items`]: No longer
+  trigger in code generated from proc-macros
+  [#8694](https://github.com/rust-lang/rust-clippy/pull/8694)
+* [`unwrap_used`]: Now lints uses of `unwrap_err`
+  [#9338](https://github.com/rust-lang/rust-clippy/pull/9338)
+* [`expect_used`]: Now lints uses of `expect_err`
+  [#9338](https://github.com/rust-lang/rust-clippy/pull/9338)
+* [`transmute_undefined_repr`]: Now longer lints if the first field is compatible
+  with the other type
+  [#9287](https://github.com/rust-lang/rust-clippy/pull/9287)
+* [`unnecessary_to_owned`]: No longer lints, if type change cased errors in
+  the caller function
+  [#9424](https://github.com/rust-lang/rust-clippy/pull/9424)
+* [`match_like_matches_macro`]: No longer lints, if there are comments inside the
+  match expression
+  [#9276](https://github.com/rust-lang/rust-clippy/pull/9276)
+* [`partialeq_to_none`]: No longer trigger in code generated from macros
+  [#9389](https://github.com/rust-lang/rust-clippy/pull/9389)
+* [`arithmetic_side_effects`]: No longer lints expressions that only use literals
+  [#9365](https://github.com/rust-lang/rust-clippy/pull/9365)
+* [`explicit_auto_deref`]: Now ignores references on block expressions when the type
+  is `Sized`, on `dyn Trait` returns and when the suggestion is non-trivial
+  [#9126](https://github.com/rust-lang/rust-clippy/pull/9126)
+* [`trait_duplication_in_bounds`]: Now better tracks bounds to avoid false positives
+  [#9167](https://github.com/rust-lang/rust-clippy/pull/9167)
+* [`format_in_format_args`]: Now suggests cases where the result is formatted again
+  [#9349](https://github.com/rust-lang/rust-clippy/pull/9349)
+* [`only_used_in_recursion`]: No longer lints on function without recursions and
+  takes external functions into account
+  [#8804](https://github.com/rust-lang/rust-clippy/pull/8804)
+* [`missing_const_for_fn`]: No longer lints in proc-macros
+  [#9308](https://github.com/rust-lang/rust-clippy/pull/9308)
+* [`non_ascii_literal`]: Allow non-ascii comments in tests and make sure `#[allow]`
+  attributes work in tests
+  [#9327](https://github.com/rust-lang/rust-clippy/pull/9327)
+* [`question_mark`]: No longer lint `if let`s with subpatterns
+  [#9348](https://github.com/rust-lang/rust-clippy/pull/9348)
+* [`needless_collect`]: No longer lints in loops
+  [#8992](https://github.com/rust-lang/rust-clippy/pull/8992)
+* [`mut_mutex_lock`]: No longer lints if the mutex is behind an immutable reference
+  [#9418](https://github.com/rust-lang/rust-clippy/pull/9418)
+* [`needless_return`]: Now ignores returns with arguments
+  [#9381](https://github.com/rust-lang/rust-clippy/pull/9381)
+* [`range_plus_one`], [`range_minus_one`]: Now ignores code with macros
+  [#9446](https://github.com/rust-lang/rust-clippy/pull/9446)
+* [`assertions_on_result_states`]: No longer lints on the unit type
+  [#9273](https://github.com/rust-lang/rust-clippy/pull/9273)
+
+### Suggestion Fixes/Improvements
+
+* [`unwrap_or_else_default`]: Now suggests `unwrap_or_default()` for empty strings
+  [#9421](https://github.com/rust-lang/rust-clippy/pull/9421)
+* [`if_then_some_else_none`]: Now also suggests `bool::then_some`
+  [#9289](https://github.com/rust-lang/rust-clippy/pull/9289)
+* [`redundant_closure_call`]: The suggestion now works for async closures
+  [#9053](https://github.com/rust-lang/rust-clippy/pull/9053)
+* [`suboptimal_flops`]: Now suggests parenthesis when they are required
+  [#9394](https://github.com/rust-lang/rust-clippy/pull/9394)
+* [`case_sensitive_file_extension_comparisons`]: Now suggests `map_or(..)` instead of `map(..).unwrap_or`
+  [#9341](https://github.com/rust-lang/rust-clippy/pull/9341)
+* Deprecated configuration values can now be updated automatically
+  [#9252](https://github.com/rust-lang/rust-clippy/pull/9252)
+* [`or_fun_call`]: Now suggest `Entry::or_default` for `Entry::or_insert(Default::default())`
+  [#9342](https://github.com/rust-lang/rust-clippy/pull/9342)
+* [`unwrap_used`]: Only suggests `expect` if [`expect_used`] is allowed
+  [#9223](https://github.com/rust-lang/rust-clippy/pull/9223)
+
+### ICE Fixes
+
+* Fix ICE in [`useless_format`] for literals
+  [#9406](https://github.com/rust-lang/rust-clippy/pull/9406)
+* Fix infinite loop in [`vec_init_then_push`]
+  [#9441](https://github.com/rust-lang/rust-clippy/pull/9441)
+* Fix ICE when reading literals with weird proc-macro spans
+  [#9303](https://github.com/rust-lang/rust-clippy/pull/9303)
 
 ## Rust 1.64
 
-Current stable, released 2022-09-22
+Released 2022-09-22
 
 [d7b5cbf0...3c7e7dbc](https://github.com/rust-lang/rust-clippy/compare/d7b5cbf0...3c7e7dbc)
 
@@ -3903,6 +4047,7 @@ Released 2018-09-13
 [`format_push_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#format_push_string
 [`from_iter_instead_of_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_iter_instead_of_collect
 [`from_over_into`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into
+[`from_raw_with_void_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_raw_with_void_ptr
 [`from_str_radix_10`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_str_radix_10
 [`future_not_send`]: https://rust-lang.github.io/rust-clippy/master/index.html#future_not_send
 [`get_first`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_first
@@ -3978,6 +4123,7 @@ Released 2018-09-13
 [`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
 [`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return
 [`let_underscore_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_drop
+[`let_underscore_future`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_future
 [`let_underscore_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_lock
 [`let_underscore_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_must_use
 [`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
@@ -3996,6 +4142,8 @@ Released 2018-09-13
 [`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map
 [`manual_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_flatten
 [`manual_instant_elapsed`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_instant_elapsed
+[`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check
+[`manual_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else
 [`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_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive
@@ -4198,6 +4346,8 @@ Released 2018-09-13
 [`same_item_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push
 [`same_name_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_name_method
 [`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some
+[`seek_from_current`]: https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current
+[`seek_to_start_instead_of_rewind`]: https://rust-lang.github.io/rust-clippy/master/index.html#seek_to_start_instead_of_rewind
 [`self_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_assignment
 [`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors
 [`self_named_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_module_files
@@ -4247,6 +4397,7 @@ Released 2018-09-13
 [`suspicious_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_splitn
 [`suspicious_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_to_owned
 [`suspicious_unary_op_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_unary_op_formatting
+[`suspicious_xor_used_as_pow`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_xor_used_as_pow
 [`swap_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#swap_ptr_to_ref
 [`tabs_in_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments
 [`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment
@@ -4277,6 +4428,7 @@ Released 2018-09-13
 [`try_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#try_err
 [`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity
 [`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds
+[`unchecked_duration_subtraction`]: https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction
 [`undocumented_unsafe_blocks`]: https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks
 [`undropped_manually_drops`]: https://rust-lang.github.io/rust-clippy/master/index.html#undropped_manually_drops
 [`unicode_not_nfc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unicode_not_nfc
@@ -4298,6 +4450,7 @@ Released 2018-09-13
 [`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed
 [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation
 [`unnecessary_owned_empty_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_owned_empty_strings
+[`unnecessary_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc
 [`unnecessary_self_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_self_imports
 [`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by
 [`unnecessary_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned
diff --git a/src/tools/clippy/CODE_OF_CONDUCT.md b/src/tools/clippy/CODE_OF_CONDUCT.md
index dec13e44a17..e3708bc4853 100644
--- a/src/tools/clippy/CODE_OF_CONDUCT.md
+++ b/src/tools/clippy/CODE_OF_CONDUCT.md
@@ -1,70 +1,3 @@
 # The Rust Code of Conduct
 
-A version of this document [can be found online](https://www.rust-lang.org/conduct.html).
-
-## Conduct
-
-**Contact**: [rust-mods@rust-lang.org](mailto:rust-mods@rust-lang.org)
-
-* We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience,
-  gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
-  religion, nationality, or other similar characteristic.
-* On IRC, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and
-  welcoming environment for all.
-* Please be kind and courteous. There's no need to be mean or rude.
-* Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and
-  numerous costs. There is seldom a right answer.
-* Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and
-  see how it works.
-* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We
-  interpret the term "harassment" as including the definition in the <a href="http://citizencodeofconduct.org/">Citizen
-  Code of Conduct</a>; if you have any lack of clarity about what might be included in that concept, please read their
-  definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups.
-* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or
-  made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation
-  team][mod_team] immediately. Whether you're a regular contributor or a newcomer, we care about making this community a
-  safe place for you and we've got your back.
-* Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome.
-
-## Moderation
-
-
-These are the policies for upholding our community's standards of conduct. If you feel that a thread needs moderation,
-please contact the [Rust moderation team][mod_team].
-
-1. Remarks that violate the Rust standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks,
-   are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.)
-2. Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed.
-3. Moderators will first respond to such remarks with a warning.
-4. If the warning is unheeded, the user will be "kicked," i.e., kicked out of the communication channel to cool off.
-5. If the user comes back and continues to make trouble, they will be banned, i.e., indefinitely excluded.
-6. Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended
-   party a genuine apology.
-7. If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a
-   different moderator, **in private**. Complaints about bans in-channel are not allowed.
-8. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate
-   situation, they should expect less leeway than others.
-
-In the Rust community we strive to go the extra step to look out for each other. Don't just aim to be technically
-unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly
-if they're off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can
-drive people away from the community entirely.
-
-And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was
-they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good
-there was something you could've communicated better — remember that it's your responsibility to make your fellow
-Rustaceans comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about
-cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their
-trust.
-
-The enforcement policies listed above apply to all official Rust venues; including official IRC channels (#rust,
-#rust-internals, #rust-tools, #rust-libs, #rustc, #rust-beginners, #rust-docs, #rust-community, #rust-lang, and #cargo);
-GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org
-(users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the
-maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider
-explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion.
-
-*Adapted from the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling) as well as the
-[Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).*
-
-[mod_team]: https://www.rust-lang.org/team.html#Moderation-team
+The Code of Conduct for this repository [can be found online](https://www.rust-lang.org/conduct.html).
diff --git a/src/tools/clippy/CONTRIBUTING.md b/src/tools/clippy/CONTRIBUTING.md
index 85f94a74ad9..3158080d2b3 100644
--- a/src/tools/clippy/CONTRIBUTING.md
+++ b/src/tools/clippy/CONTRIBUTING.md
@@ -23,6 +23,7 @@ All contributors are expected to follow the [Rust Code of Conduct].
   - [Issue and PR triage](#issue-and-pr-triage)
   - [Bors and Homu](#bors-and-homu)
   - [Contributions](#contributions)
+  - [License](#license)
 
 [Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/clippy
 [Rust Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct
@@ -245,6 +246,38 @@ Contributions to Clippy should be made in the form of GitHub pull requests. Each
 be reviewed by a core contributor (someone with permission to land patches) and either landed in the
 main tree or given feedback for changes that would be required.
 
+All PRs should include a `changelog` entry with a short comment explaining the change. The rule of thumb is basically,
+"what do you believe is important from an outsider's perspective?" Often, PRs are only related to a single property of a
+lint, and then it's good to mention that one. Otherwise, it's better to include too much detail than too little.
+
+Clippy's [changelog] is created from these comments. Every release, someone gets all commits from bors with a
+`changelog: XYZ` entry and combines them into the changelog. This is a manual process.
+
+Examples:
+- New lint
+  ```
+  changelog: new lint: [`missing_trait_methods`]
+  ```
+- False positive fix
+  ```
+  changelog: Fix [`unused_peekable`] false positive when peeked in a closure or called as `f(&mut peekable)`
+  ```
+- Purely internal change
+  ```
+  changelog: none
+  ```
+
+Note this it is fine for a PR to include multiple `changelog` entries, e.g.:
+```
+changelog: Something 1
+changelog: Something 2
+changelog: Something 3
+```
+
+[changelog]: CHANGELOG.md
+
+## License
+
 All code in this repository is under the [Apache-2.0] or the [MIT] license.
 
 <!-- adapted from https://github.com/servo/servo/blob/master/CONTRIBUTING.md -->
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index 60200a88b85..fe425a2fb99 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.1.66"
+version = "0.1.67"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index a8a6b86d2a1..f74de7de42b 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -1,6 +1,6 @@
 # Clippy
 
-[![Clippy Test](https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test/badge.svg?branch=auto&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test%22+event%3Apush+branch%3Aauto)
+[![Clippy Test](https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test%20(bors)/badge.svg?branch=auto&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test+(bors)%22+event%3Apush+branch%3Aauto)
 [![License: MIT OR Apache-2.0](https://img.shields.io/crates/l/clippy.svg)](#license)
 
 A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
@@ -204,12 +204,6 @@ lints can be configured and the meaning of the variables.
 >
 > `clippy.toml` or `.clippy.toml` cannot be used to allow/deny lints.
 
-> **Note**
->
-> Configuration changes will not apply for code that has already been compiled and cached under `./target/`;
-> for example, adding a new string to `doc-valid-idents` may still result in Clippy flagging that string. To be sure
-> that any configuration changes are applied, you may want to run `cargo clean` and re-compile your crate from scratch.
-
 To deactivate the “for further information visit *lint-link*” message you can
 define the `CLIPPY_DISABLE_DOCS_LINKS` environment variable.
 
diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml
index 2ac3b4fe2ed..510c7e852af 100644
--- a/src/tools/clippy/clippy_dev/Cargo.toml
+++ b/src/tools/clippy/clippy_dev/Cargo.toml
@@ -10,7 +10,6 @@ indoc = "1.0"
 itertools = "0.10.1"
 opener = "0.5"
 shell-escape = "0.1"
-tempfile = "3.2"
 walkdir = "2.3"
 
 [features]
diff --git a/src/tools/clippy/clippy_dev/src/lint.rs b/src/tools/clippy/clippy_dev/src/lint.rs
index 71005449b4d..aafd0f71a59 100644
--- a/src/tools/clippy/clippy_dev/src/lint.rs
+++ b/src/tools/clippy/clippy_dev/src/lint.rs
@@ -36,20 +36,12 @@ pub fn run<'a>(path: &str, args: impl Iterator<Item = &'a String>) {
     } else {
         exit_if_err(Command::new("cargo").arg("build").status());
 
-        // Run in a tempdir as changes to clippy do not retrigger linting
-        let target = tempfile::Builder::new()
-            .prefix("clippy")
-            .tempdir()
-            .expect("failed to create tempdir");
-
         let status = Command::new(cargo_clippy_path())
             .arg("clippy")
             .args(args)
             .current_dir(path)
-            .env("CARGO_TARGET_DIR", target.as_ref())
             .status();
 
-        target.close().expect("failed to remove tempdir");
         exit_if_err(status);
     }
 }
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index e690bc369cd..837618c9294 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -3,7 +3,7 @@ use aho_corasick::AhoCorasickBuilder;
 use indoc::writedoc;
 use itertools::Itertools;
 use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
-use std::collections::{BTreeSet, HashMap, HashSet};
+use std::collections::{HashMap, HashSet};
 use std::ffi::OsStr;
 use std::fmt::Write;
 use std::fs::{self, OpenOptions};
@@ -36,6 +36,60 @@ pub enum UpdateMode {
 pub fn update(update_mode: UpdateMode) {
     let (lints, deprecated_lints, renamed_lints) = gather_all();
     generate_lint_files(update_mode, &lints, &deprecated_lints, &renamed_lints);
+    remove_old_files(update_mode);
+}
+
+/// Remove files no longer needed after <https://github.com/rust-lang/rust-clippy/pull/9541>
+/// that may be reintroduced unintentionally
+///
+/// FIXME: This is a temporary measure that should be removed when there are no more PRs that
+/// include the stray files
+fn remove_old_files(update_mode: UpdateMode) {
+    let mut failed = false;
+    let mut remove_file = |path: &Path| match update_mode {
+        UpdateMode::Check => {
+            if path.exists() {
+                failed = true;
+                println!("unexpected file: {}", path.display());
+            }
+        },
+        UpdateMode::Change => {
+            if fs::remove_file(path).is_ok() {
+                println!("removed file: {}", path.display());
+            }
+        },
+    };
+
+    let files = [
+        "clippy_lints/src/lib.register_all.rs",
+        "clippy_lints/src/lib.register_cargo.rs",
+        "clippy_lints/src/lib.register_complexity.rs",
+        "clippy_lints/src/lib.register_correctness.rs",
+        "clippy_lints/src/lib.register_internal.rs",
+        "clippy_lints/src/lib.register_lints.rs",
+        "clippy_lints/src/lib.register_nursery.rs",
+        "clippy_lints/src/lib.register_pedantic.rs",
+        "clippy_lints/src/lib.register_perf.rs",
+        "clippy_lints/src/lib.register_restriction.rs",
+        "clippy_lints/src/lib.register_style.rs",
+        "clippy_lints/src/lib.register_suspicious.rs",
+        "src/docs.rs",
+    ];
+
+    for file in files {
+        remove_file(Path::new(file));
+    }
+
+    if let Ok(docs_dir) = fs::read_dir("src/docs") {
+        for doc_file in docs_dir {
+            let path = doc_file.unwrap().path();
+            remove_file(&path);
+        }
+    }
+
+    if failed {
+        exit_with_failure();
+    }
 }
 
 fn generate_lint_files(
@@ -104,9 +158,9 @@ fn generate_lint_files(
     );
 
     process_file(
-        "clippy_lints/src/lib.register_lints.rs",
+        "clippy_lints/src/declared_lints.rs",
         update_mode,
-        &gen_register_lint_list(internal_lints.iter(), usable_lints.iter()),
+        &gen_declared_lints(internal_lints.iter(), usable_lints.iter()),
     );
     process_file(
         "clippy_lints/src/lib.deprecated.rs",
@@ -114,26 +168,6 @@ fn generate_lint_files(
         &gen_deprecated(deprecated_lints),
     );
 
-    let all_group_lints = usable_lints.iter().filter(|l| {
-        matches!(
-            &*l.group,
-            "correctness" | "suspicious" | "style" | "complexity" | "perf"
-        )
-    });
-    let content = gen_lint_group_list("all", all_group_lints);
-    process_file("clippy_lints/src/lib.register_all.rs", update_mode, &content);
-
-    update_docs(update_mode, &usable_lints);
-
-    for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter().chain(internal_lints)) {
-        let content = gen_lint_group_list(&lint_group, lints.iter());
-        process_file(
-            format!("clippy_lints/src/lib.register_{lint_group}.rs"),
-            update_mode,
-            &content,
-        );
-    }
-
     let content = gen_deprecated_lints_test(deprecated_lints);
     process_file("tests/ui/deprecated.rs", update_mode, &content);
 
@@ -141,62 +175,6 @@ fn generate_lint_files(
     process_file("tests/ui/rename.rs", update_mode, &content);
 }
 
-fn update_docs(update_mode: UpdateMode, usable_lints: &[Lint]) {
-    replace_region_in_file(update_mode, Path::new("src/docs.rs"), "docs! {\n", "\n}\n", |res| {
-        for name in usable_lints.iter().map(|lint| lint.name.clone()).sorted() {
-            writeln!(res, r#"    "{name}","#).unwrap();
-        }
-    });
-
-    if update_mode == UpdateMode::Check {
-        let mut extra = BTreeSet::new();
-        let mut lint_names = usable_lints
-            .iter()
-            .map(|lint| lint.name.clone())
-            .collect::<BTreeSet<_>>();
-        for file in std::fs::read_dir("src/docs").unwrap() {
-            let filename = file.unwrap().file_name().into_string().unwrap();
-            if let Some(name) = filename.strip_suffix(".txt") {
-                if !lint_names.remove(name) {
-                    extra.insert(name.to_string());
-                }
-            }
-        }
-
-        let failed = print_lint_names("extra lint docs:", &extra) | print_lint_names("missing lint docs:", &lint_names);
-
-        if failed {
-            exit_with_failure();
-        }
-    } else {
-        if std::fs::remove_dir_all("src/docs").is_err() {
-            eprintln!("could not remove src/docs directory");
-        }
-        if std::fs::create_dir("src/docs").is_err() {
-            eprintln!("could not recreate src/docs directory");
-        }
-    }
-    for lint in usable_lints {
-        process_file(
-            Path::new("src/docs").join(lint.name.clone() + ".txt"),
-            update_mode,
-            &lint.documentation,
-        );
-    }
-}
-
-fn print_lint_names(header: &str, lints: &BTreeSet<String>) -> bool {
-    if lints.is_empty() {
-        return false;
-    }
-    println!("{header}");
-    for lint in lints.iter().sorted() {
-        println!("    {lint}");
-    }
-    println!();
-    true
-}
-
 pub fn print_lints() {
     let (lint_list, _, _) = gather_all();
     let usable_lints = Lint::usable_lints(&lint_list);
@@ -641,26 +619,17 @@ struct Lint {
     desc: String,
     module: String,
     declaration_range: Range<usize>,
-    documentation: String,
 }
 
 impl Lint {
     #[must_use]
-    fn new(
-        name: &str,
-        group: &str,
-        desc: &str,
-        module: &str,
-        declaration_range: Range<usize>,
-        documentation: String,
-    ) -> Self {
+    fn new(name: &str, group: &str, desc: &str, module: &str, declaration_range: Range<usize>) -> Self {
         Self {
             name: name.to_lowercase(),
             group: group.into(),
             desc: remove_line_splices(desc),
             module: module.into(),
             declaration_range,
-            documentation,
         }
     }
 
@@ -716,25 +685,6 @@ impl RenamedLint {
     }
 }
 
-/// Generates the code for registering a group
-fn gen_lint_group_list<'a>(group_name: &str, lints: impl Iterator<Item = &'a Lint>) -> String {
-    let mut details: Vec<_> = lints.map(|l| (&l.module, l.name.to_uppercase())).collect();
-    details.sort_unstable();
-
-    let mut output = GENERATED_FILE_COMMENT.to_string();
-
-    let _ = writeln!(
-        output,
-        "store.register_group(true, \"clippy::{group_name}\", Some(\"clippy_{group_name}\"), vec![",
-    );
-    for (module, name) in details {
-        let _ = writeln!(output, "    LintId::of({module}::{name}),");
-    }
-    output.push_str("])\n");
-
-    output
-}
-
 /// Generates the `register_removed` code
 #[must_use]
 fn gen_deprecated(lints: &[DeprecatedLint]) -> String {
@@ -759,7 +709,7 @@ fn gen_deprecated(lints: &[DeprecatedLint]) -> String {
 
 /// Generates the code for registering lints
 #[must_use]
-fn gen_register_lint_list<'a>(
+fn gen_declared_lints<'a>(
     internal_lints: impl Iterator<Item = &'a Lint>,
     usable_lints: impl Iterator<Item = &'a Lint>,
 ) -> String {
@@ -770,15 +720,15 @@ fn gen_register_lint_list<'a>(
     details.sort_unstable();
 
     let mut output = GENERATED_FILE_COMMENT.to_string();
-    output.push_str("store.register_lints(&[\n");
+    output.push_str("pub(crate) static LINTS: &[&crate::LintInfo] = &[\n");
 
     for (is_public, module_name, lint_name) in details {
         if !is_public {
             output.push_str("    #[cfg(feature = \"internal\")]\n");
         }
-        let _ = writeln!(output, "    {module_name}::{lint_name},");
+        let _ = writeln!(output, "    crate::{module_name}::{lint_name}_INFO,");
     }
-    output.push_str("])\n");
+    output.push_str("];\n");
 
     output
 }
@@ -910,35 +860,26 @@ fn parse_contents(contents: &str, module: &str, lints: &mut Vec<Lint>) {
          }| token_kind == &TokenKind::Ident && *content == "declare_clippy_lint",
     ) {
         let start = range.start;
-        let mut docs = String::with_capacity(128);
-        let mut iter = iter.by_ref().filter(|t| !matches!(t.token_kind, TokenKind::Whitespace));
+        let mut iter = iter
+            .by_ref()
+            .filter(|t| !matches!(t.token_kind, TokenKind::Whitespace | TokenKind::LineComment { .. }));
         // matches `!{`
         match_tokens!(iter, Bang OpenBrace);
-        let mut in_code = false;
-        while let Some(t) = iter.next() {
-            match t.token_kind {
-                TokenKind::LineComment { .. } => {
-                    if let Some(line) = t.content.strip_prefix("/// ").or_else(|| t.content.strip_prefix("///")) {
-                        if line.starts_with("```") {
-                            docs += "```\n";
-                            in_code = !in_code;
-                        } else if !(in_code && line.starts_with("# ")) {
-                            docs += line;
-                            docs.push('\n');
-                        }
-                    }
-                },
-                TokenKind::Pound => {
-                    match_tokens!(iter, OpenBracket Ident Colon Colon Ident Eq Literal{..} CloseBracket Ident);
-                    break;
-                },
-                TokenKind::Ident => {
-                    break;
-                },
-                _ => {},
-            }
+        match iter.next() {
+            // #[clippy::version = "version"] pub
+            Some(LintDeclSearchResult {
+                token_kind: TokenKind::Pound,
+                ..
+            }) => {
+                match_tokens!(iter, OpenBracket Ident Colon Colon Ident Eq Literal{..} CloseBracket Ident);
+            },
+            // pub
+            Some(LintDeclSearchResult {
+                token_kind: TokenKind::Ident,
+                ..
+            }) => (),
+            _ => continue,
         }
-        docs.pop(); // remove final newline
 
         let (name, group, desc) = match_tokens!(
             iter,
@@ -956,7 +897,7 @@ fn parse_contents(contents: &str, module: &str, lints: &mut Vec<Lint>) {
             ..
         }) = iter.next()
         {
-            lints.push(Lint::new(name, group, desc, module, start..range.end, docs));
+            lints.push(Lint::new(name, group, desc, module, start..range.end));
         }
     }
 }
@@ -1186,7 +1127,6 @@ mod tests {
                 "\"really long text\"",
                 "module_name",
                 Range::default(),
-                String::new(),
             ),
             Lint::new(
                 "doc_markdown",
@@ -1194,7 +1134,6 @@ mod tests {
                 "\"single line\"",
                 "module_name",
                 Range::default(),
-                String::new(),
             ),
         ];
         assert_eq!(expected, result);
@@ -1234,7 +1173,6 @@ mod tests {
                 "\"abc\"",
                 "module_name",
                 Range::default(),
-                String::new(),
             ),
             Lint::new(
                 "should_assert_eq2",
@@ -1242,7 +1180,6 @@ mod tests {
                 "\"abc\"",
                 "module_name",
                 Range::default(),
-                String::new(),
             ),
             Lint::new(
                 "should_assert_eq2",
@@ -1250,7 +1187,6 @@ mod tests {
                 "\"abc\"",
                 "module_name",
                 Range::default(),
-                String::new(),
             ),
         ];
         let expected = vec![Lint::new(
@@ -1259,7 +1195,6 @@ mod tests {
             "\"abc\"",
             "module_name",
             Range::default(),
-            String::new(),
         )];
         assert_eq!(expected, Lint::usable_lints(&lints));
     }
@@ -1267,51 +1202,22 @@ mod tests {
     #[test]
     fn test_by_lint_group() {
         let lints = vec![
-            Lint::new(
-                "should_assert_eq",
-                "group1",
-                "\"abc\"",
-                "module_name",
-                Range::default(),
-                String::new(),
-            ),
+            Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
             Lint::new(
                 "should_assert_eq2",
                 "group2",
                 "\"abc\"",
                 "module_name",
                 Range::default(),
-                String::new(),
-            ),
-            Lint::new(
-                "incorrect_match",
-                "group1",
-                "\"abc\"",
-                "module_name",
-                Range::default(),
-                String::new(),
             ),
+            Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
         ];
         let mut expected: HashMap<String, Vec<Lint>> = HashMap::new();
         expected.insert(
             "group1".to_string(),
             vec![
-                Lint::new(
-                    "should_assert_eq",
-                    "group1",
-                    "\"abc\"",
-                    "module_name",
-                    Range::default(),
-                    String::new(),
-                ),
-                Lint::new(
-                    "incorrect_match",
-                    "group1",
-                    "\"abc\"",
-                    "module_name",
-                    Range::default(),
-                    String::new(),
-                ),
+                Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
+                Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
             ],
         );
         expected.insert(
@@ -1322,7 +1228,6 @@ mod tests {
                 "\"abc\"",
                 "module_name",
                 Range::default(),
-                String::new(),
             )],
         );
         assert_eq!(expected, Lint::by_lint_group(lints.into_iter()));
@@ -1357,48 +1262,4 @@ mod tests {
 
         assert_eq!(expected, gen_deprecated(&lints));
     }
-
-    #[test]
-    fn test_gen_lint_group_list() {
-        let lints = vec![
-            Lint::new(
-                "abc",
-                "group1",
-                "\"abc\"",
-                "module_name",
-                Range::default(),
-                String::new(),
-            ),
-            Lint::new(
-                "should_assert_eq",
-                "group1",
-                "\"abc\"",
-                "module_name",
-                Range::default(),
-                String::new(),
-            ),
-            Lint::new(
-                "internal",
-                "internal_style",
-                "\"abc\"",
-                "module_name",
-                Range::default(),
-                String::new(),
-            ),
-        ];
-        let expected = GENERATED_FILE_COMMENT.to_string()
-            + &[
-                "store.register_group(true, \"clippy::group1\", Some(\"clippy_group1\"), vec![",
-                "    LintId::of(module_name::ABC),",
-                "    LintId::of(module_name::INTERNAL),",
-                "    LintId::of(module_name::SHOULD_ASSERT_EQ),",
-                "])",
-            ]
-            .join("\n")
-            + "\n";
-
-        let result = gen_lint_group_list("group1", lints.iter());
-
-        assert_eq!(expected, result);
-    }
 }
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 6fbd6401ef3..aedff24c12c 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_lints"
-version = "0.1.66"
+version = "0.1.67"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
@@ -11,6 +11,7 @@ edition = "2021"
 [dependencies]
 cargo_metadata = "0.14"
 clippy_utils = { path = "../clippy_utils" }
+declare_clippy_lint = { path = "../declare_clippy_lint" }
 if_chain = "1.0"
 itertools = "0.10.1"
 pulldown-cmark = { version = "0.9", default-features = false }
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 0bd1f8b784e..ecf8e83375d 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -11,14 +11,14 @@ use rustc_errors::Applicability;
 use rustc_hir::{
     Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind,
 };
-use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
-use rustc_span::sym;
 use rustc_span::symbol::Symbol;
+use rustc_span::{sym, DUMMY_SP};
 use semver::Version;
 
 static UNIX_SYSTEMS: &[&str] = &[
@@ -303,6 +303,26 @@ declare_lint_pass!(Attributes => [
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Attributes {
+    fn check_crate(&mut self, cx: &LateContext<'tcx>) {
+        for (name, level) in &cx.sess().opts.lint_opts {
+            if name == "clippy::restriction" && *level > Level::Allow {
+                span_lint_and_then(
+                    cx,
+                    BLANKET_CLIPPY_RESTRICTION_LINTS,
+                    DUMMY_SP,
+                    "`clippy::restriction` is not meant to be enabled as a group",
+                    |diag| {
+                        diag.note(format!(
+                            "because of the command line `--{} clippy::restriction`",
+                            level.as_str()
+                        ));
+                        diag.help("enable the restriction lints you need individually");
+                    },
+                );
+            }
+        }
+    }
+
     fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) {
         if let Some(items) = &attr.meta_item_list() {
             if let Some(ident) = attr.ident() {
@@ -358,7 +378,9 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
                                                         | "enum_glob_use"
                                                         | "redundant_pub_crate"
                                                         | "macro_use_imports"
-                                                        | "unsafe_removed_from_name",
+                                                        | "unsafe_removed_from_name"
+                                                        | "module_name_repetitions"
+                                                        | "single_component_path_imports"
                                                 )
                                             })
                                         {
@@ -441,9 +463,9 @@ fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMe
                     cx,
                     BLANKET_CLIPPY_RESTRICTION_LINTS,
                     lint.span(),
-                    "restriction lints are not meant to be all enabled",
+                    "`clippy::restriction` is not meant to be enabled as a group",
                     None,
-                    "try enabling only the lints you really need",
+                    "enable the restriction lints you need individually",
                 );
             }
         }
@@ -464,6 +486,11 @@ fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem
         return;
     }
 
+    // Check if the attribute is in an external macro and therefore out of the developer's control
+    if in_external_macro(cx.sess(), attr.span) {
+        return;
+    }
+
     span_lint_and_help(
         cx,
         ALLOW_ATTRIBUTES_WITHOUT_REASON,
diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
index 34717811866..d40a385435a 100644
--- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
+++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::{match_def_path, paths};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def::{Namespace, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{AsyncGeneratorKind, Body, BodyId, GeneratorKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -189,7 +188,7 @@ impl LateLintPass<'_> for AwaitHolding {
     fn check_crate(&mut self, cx: &LateContext<'_>) {
         for conf in &self.conf_invalid_types {
             let segs: Vec<_> = conf.path().split("::").collect();
-            if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, Some(Namespace::TypeNS)) {
+            for id in clippy_utils::def_path_def_ids(cx, &segs) {
                 self.def_ids.insert(id, conf.clone());
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs b/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
index 001d74c2605..bdb3a011602 100644
--- a/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
@@ -1,9 +1,10 @@
+use clippy_utils::higher::If;
 use rustc_ast::LitKind;
 use rustc_hir::{Block, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use clippy_utils::{diagnostics::span_lint_and_then, is_else_clause, is_integer_literal, sugg::Sugg};
+use clippy_utils::{diagnostics::span_lint_and_then, in_constant, is_else_clause, is_integer_literal, sugg::Sugg};
 use rustc_errors::Applicability;
 
 declare_clippy_lint! {
@@ -12,7 +13,7 @@ declare_clippy_lint! {
     /// this lint suggests using a `from()` function or an `as` coercion.
     ///
     /// ### Why is this bad?
-    /// Coercion or `from()` is idiomatic way to convert bool to a number.
+    /// Coercion or `from()` is another way to convert bool to a number.
     /// Both methods are guaranteed to return 1 for true, and 0 for false.
     ///
     /// See https://doc.rust-lang.org/std/primitive.bool.html#impl-From%3Cbool%3E
@@ -38,23 +39,23 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "1.65.0"]
     pub BOOL_TO_INT_WITH_IF,
-    style,
+    pedantic,
     "using if to convert bool to int"
 }
 declare_lint_pass!(BoolToIntWithIf => [BOOL_TO_INT_WITH_IF]);
 
 impl<'tcx> LateLintPass<'tcx> for BoolToIntWithIf {
-    fn check_expr(&mut self, ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
-        if !expr.span.from_expansion() {
-            check_if_else(ctx, expr);
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
+        if !expr.span.from_expansion() && !in_constant(cx, expr.hir_id) {
+            check_if_else(cx, expr);
         }
     }
 }
 
-fn check_if_else<'tcx>(ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
-    if let ExprKind::If(check, then, Some(else_)) = expr.kind
+fn check_if_else<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
+    if let Some(If { cond, then, r#else: Some(r#else) }) = If::hir(expr)
         && let Some(then_lit) = int_literal(then)
-        && let Some(else_lit) = int_literal(else_)
+        && let Some(else_lit) = int_literal(r#else)
     {
         let inverted = if is_integer_literal(then_lit, 1) && is_integer_literal(else_lit, 0) {
             false
@@ -66,17 +67,17 @@ fn check_if_else<'tcx>(ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx
         };
         let mut applicability = Applicability::MachineApplicable;
         let snippet = {
-            let mut sugg = Sugg::hir_with_applicability(ctx, check, "..", &mut applicability);
+            let mut sugg = Sugg::hir_with_applicability(cx, cond, "..", &mut applicability);
             if inverted {
                 sugg = !sugg;
             }
             sugg
         };
 
-        let ty = ctx.typeck_results().expr_ty(then_lit); // then and else must be of same type
+        let ty = cx.typeck_results().expr_ty(then_lit); // then and else must be of same type
 
         let suggestion = {
-            let wrap_in_curly = is_else_clause(ctx.tcx, expr);
+            let wrap_in_curly = is_else_clause(cx.tcx, expr);
             let mut s = Sugg::NonParen(format!("{ty}::from({snippet})").into());
             if wrap_in_curly {
                 s = s.blockify();
@@ -87,7 +88,7 @@ fn check_if_else<'tcx>(ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx
         let into_snippet = snippet.clone().maybe_par();
         let as_snippet = snippet.as_ty(ty);
 
-        span_lint_and_then(ctx,
+        span_lint_and_then(cx,
             BOOL_TO_INT_WITH_IF,
             expr.span,
             "boolean to int conversion using if",
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index 08164c0b654..939bdbcdc7c 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -481,7 +481,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
     }
 }
 
-fn implements_ord<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool {
+fn implements_ord(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let ty = cx.typeck_results().expr_ty(expr);
     cx.tcx
         .get_diagnostic_item(sym::Ord)
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 88deb4565eb..adbcfd3189b 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
@@ -2,12 +2,11 @@ use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::expr_or_init;
 use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
-use rustc_ast::ast;
-use rustc_attr::IntType;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, FloatTy, Ty};
+use rustc_target::abi::IntegerType;
 
 use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
 
@@ -122,7 +121,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
             let cast_from_ptr_size = def.repr().int.map_or(true, |ty| {
                 matches!(
                     ty,
-                    IntType::SignedInt(ast::IntTy::Isize) | IntType::UnsignedInt(ast::UintTy::Usize)
+                    IntegerType::Pointer(_),
                 )
             });
             let suffix = match (cast_from_ptr_size, is_isize_or_usize(cast_to)) {
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index b72c4c772f1..7148b5e6ebf 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -593,7 +593,7 @@ declare_clippy_lint! {
     /// let _: *mut [u8] = std::ptr::slice_from_raw_parts_mut(ptr, len);
     /// ```
     /// [safety requirements]: https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html#safety
-    #[clippy::version = "1.64.0"]
+    #[clippy::version = "1.65.0"]
     pub CAST_SLICE_FROM_RAW_PARTS,
     suspicious,
     "casting a slice created from a pointer and length to a slice pointer"
diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
index 77af3b53d63..1c3a89a9782 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
@@ -4,11 +4,11 @@ use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::for_each_expr;
-use clippy_utils::LimitStack;
+use clippy_utils::{get_async_fn_body, is_async_fn, LimitStack};
 use core::ops::ControlFlow;
 use rustc_ast::ast::Attribute;
 use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, ExprKind, FnDecl, HirId};
+use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
@@ -56,15 +56,13 @@ impl CognitiveComplexity {
         cx: &LateContext<'tcx>,
         kind: FnKind<'tcx>,
         decl: &'tcx FnDecl<'_>,
-        body: &'tcx Body<'_>,
+        expr: &'tcx Expr<'_>,
         body_span: Span,
     ) {
         if body_span.from_expansion() {
             return;
         }
 
-        let expr = body.value;
-
         let mut cc = 1u64;
         let mut returns = 0u64;
         let _: Option<!> = for_each_expr(expr, |e| {
@@ -146,7 +144,18 @@ impl<'tcx> LateLintPass<'tcx> for CognitiveComplexity {
     ) {
         let def_id = cx.tcx.hir().local_def_id(hir_id);
         if !cx.tcx.has_attr(def_id.to_def_id(), sym::test) {
-            self.check(cx, kind, decl, body, span);
+            let expr = if is_async_fn(kind) {
+                match get_async_fn_body(cx.tcx, body) {
+                    Some(b) => b,
+                    None => {
+                        return;
+                    },
+                }
+            } else {
+                body.value
+            };
+
+            self.check(cx, kind, decl, expr, span);
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
new file mode 100644
index 00000000000..0d3fc43a644
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -0,0 +1,628 @@
+// This file was generated by `cargo dev update_lints`.
+// Use that command to update this file and do not edit by hand.
+// Manual edits will be overwritten.
+
+pub(crate) static LINTS: &[&crate::LintInfo] = &[
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::clippy_lints_internal::CLIPPY_LINTS_INTERNAL_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::compiler_lint_functions::COMPILER_LINT_FUNCTIONS_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::if_chain_style::IF_CHAIN_STYLE_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::interning_defined_symbol::INTERNING_DEFINED_SYMBOL_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::interning_defined_symbol::UNNECESSARY_SYMBOL_STR_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::invalid_paths::INVALID_PATHS_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::lint_without_lint_pass::DEFAULT_DEPRECATION_REASON_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::lint_without_lint_pass::DEFAULT_LINT_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::lint_without_lint_pass::INVALID_CLIPPY_VERSION_ATTRIBUTE_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::lint_without_lint_pass::LINT_WITHOUT_LINT_PASS_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::msrv_attr_impl::MISSING_MSRV_ATTR_IMPL_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::outer_expn_data_pass::OUTER_EXPN_EXPN_DATA_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::produce_ice::PRODUCE_ICE_INFO,
+    #[cfg(feature = "internal")]
+    crate::utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH_INFO,
+    crate::almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE_INFO,
+    crate::approx_const::APPROX_CONSTANT_INFO,
+    crate::as_conversions::AS_CONVERSIONS_INFO,
+    crate::asm_syntax::INLINE_ASM_X86_ATT_SYNTAX_INFO,
+    crate::asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX_INFO,
+    crate::assertions_on_constants::ASSERTIONS_ON_CONSTANTS_INFO,
+    crate::assertions_on_result_states::ASSERTIONS_ON_RESULT_STATES_INFO,
+    crate::async_yields_async::ASYNC_YIELDS_ASYNC_INFO,
+    crate::attrs::ALLOW_ATTRIBUTES_WITHOUT_REASON_INFO,
+    crate::attrs::BLANKET_CLIPPY_RESTRICTION_LINTS_INFO,
+    crate::attrs::DEPRECATED_CFG_ATTR_INFO,
+    crate::attrs::DEPRECATED_SEMVER_INFO,
+    crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
+    crate::attrs::INLINE_ALWAYS_INFO,
+    crate::attrs::MISMATCHED_TARGET_OS_INFO,
+    crate::attrs::USELESS_ATTRIBUTE_INFO,
+    crate::await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE_INFO,
+    crate::await_holding_invalid::AWAIT_HOLDING_LOCK_INFO,
+    crate::await_holding_invalid::AWAIT_HOLDING_REFCELL_REF_INFO,
+    crate::blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS_INFO,
+    crate::bool_assert_comparison::BOOL_ASSERT_COMPARISON_INFO,
+    crate::bool_to_int_with_if::BOOL_TO_INT_WITH_IF_INFO,
+    crate::booleans::NONMINIMAL_BOOL_INFO,
+    crate::booleans::OVERLY_COMPLEX_BOOL_EXPR_INFO,
+    crate::borrow_deref_ref::BORROW_DEREF_REF_INFO,
+    crate::box_default::BOX_DEFAULT_INFO,
+    crate::cargo::CARGO_COMMON_METADATA_INFO,
+    crate::cargo::MULTIPLE_CRATE_VERSIONS_INFO,
+    crate::cargo::NEGATIVE_FEATURE_NAMES_INFO,
+    crate::cargo::REDUNDANT_FEATURE_NAMES_INFO,
+    crate::cargo::WILDCARD_DEPENDENCIES_INFO,
+    crate::casts::AS_PTR_CAST_MUT_INFO,
+    crate::casts::AS_UNDERSCORE_INFO,
+    crate::casts::BORROW_AS_PTR_INFO,
+    crate::casts::CAST_ABS_TO_UNSIGNED_INFO,
+    crate::casts::CAST_ENUM_CONSTRUCTOR_INFO,
+    crate::casts::CAST_ENUM_TRUNCATION_INFO,
+    crate::casts::CAST_LOSSLESS_INFO,
+    crate::casts::CAST_NAN_TO_INT_INFO,
+    crate::casts::CAST_POSSIBLE_TRUNCATION_INFO,
+    crate::casts::CAST_POSSIBLE_WRAP_INFO,
+    crate::casts::CAST_PRECISION_LOSS_INFO,
+    crate::casts::CAST_PTR_ALIGNMENT_INFO,
+    crate::casts::CAST_REF_TO_MUT_INFO,
+    crate::casts::CAST_SIGN_LOSS_INFO,
+    crate::casts::CAST_SLICE_DIFFERENT_SIZES_INFO,
+    crate::casts::CAST_SLICE_FROM_RAW_PARTS_INFO,
+    crate::casts::CHAR_LIT_AS_U8_INFO,
+    crate::casts::FN_TO_NUMERIC_CAST_INFO,
+    crate::casts::FN_TO_NUMERIC_CAST_ANY_INFO,
+    crate::casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION_INFO,
+    crate::casts::PTR_AS_PTR_INFO,
+    crate::casts::UNNECESSARY_CAST_INFO,
+    crate::checked_conversions::CHECKED_CONVERSIONS_INFO,
+    crate::cognitive_complexity::COGNITIVE_COMPLEXITY_INFO,
+    crate::collapsible_if::COLLAPSIBLE_ELSE_IF_INFO,
+    crate::collapsible_if::COLLAPSIBLE_IF_INFO,
+    crate::comparison_chain::COMPARISON_CHAIN_INFO,
+    crate::copies::BRANCHES_SHARING_CODE_INFO,
+    crate::copies::IFS_SAME_COND_INFO,
+    crate::copies::IF_SAME_THEN_ELSE_INFO,
+    crate::copies::SAME_FUNCTIONS_IN_IF_CONDITION_INFO,
+    crate::copy_iterator::COPY_ITERATOR_INFO,
+    crate::crate_in_macro_def::CRATE_IN_MACRO_DEF_INFO,
+    crate::create_dir::CREATE_DIR_INFO,
+    crate::dbg_macro::DBG_MACRO_INFO,
+    crate::default::DEFAULT_TRAIT_ACCESS_INFO,
+    crate::default::FIELD_REASSIGN_WITH_DEFAULT_INFO,
+    crate::default_instead_of_iter_empty::DEFAULT_INSTEAD_OF_ITER_EMPTY_INFO,
+    crate::default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK_INFO,
+    crate::default_union_representation::DEFAULT_UNION_REPRESENTATION_INFO,
+    crate::dereference::EXPLICIT_AUTO_DEREF_INFO,
+    crate::dereference::EXPLICIT_DEREF_METHODS_INFO,
+    crate::dereference::NEEDLESS_BORROW_INFO,
+    crate::dereference::REF_BINDING_TO_REFERENCE_INFO,
+    crate::derivable_impls::DERIVABLE_IMPLS_INFO,
+    crate::derive::DERIVE_HASH_XOR_EQ_INFO,
+    crate::derive::DERIVE_ORD_XOR_PARTIAL_ORD_INFO,
+    crate::derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ_INFO,
+    crate::derive::EXPL_IMPL_CLONE_ON_COPY_INFO,
+    crate::derive::UNSAFE_DERIVE_DESERIALIZE_INFO,
+    crate::disallowed_macros::DISALLOWED_MACROS_INFO,
+    crate::disallowed_methods::DISALLOWED_METHODS_INFO,
+    crate::disallowed_names::DISALLOWED_NAMES_INFO,
+    crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO,
+    crate::disallowed_types::DISALLOWED_TYPES_INFO,
+    crate::doc::DOC_LINK_WITH_QUOTES_INFO,
+    crate::doc::DOC_MARKDOWN_INFO,
+    crate::doc::MISSING_ERRORS_DOC_INFO,
+    crate::doc::MISSING_PANICS_DOC_INFO,
+    crate::doc::MISSING_SAFETY_DOC_INFO,
+    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,
+    crate::empty_drop::EMPTY_DROP_INFO,
+    crate::empty_enum::EMPTY_ENUM_INFO,
+    crate::empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS_INFO,
+    crate::entry::MAP_ENTRY_INFO,
+    crate::enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT_INFO,
+    crate::enum_variants::ENUM_VARIANT_NAMES_INFO,
+    crate::enum_variants::MODULE_INCEPTION_INFO,
+    crate::enum_variants::MODULE_NAME_REPETITIONS_INFO,
+    crate::equatable_if_let::EQUATABLE_IF_LET_INFO,
+    crate::escape::BOXED_LOCAL_INFO,
+    crate::eta_reduction::REDUNDANT_CLOSURE_INFO,
+    crate::eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS_INFO,
+    crate::excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS_INFO,
+    crate::excessive_bools::STRUCT_EXCESSIVE_BOOLS_INFO,
+    crate::exhaustive_items::EXHAUSTIVE_ENUMS_INFO,
+    crate::exhaustive_items::EXHAUSTIVE_STRUCTS_INFO,
+    crate::exit::EXIT_INFO,
+    crate::explicit_write::EXPLICIT_WRITE_INFO,
+    crate::fallible_impl_from::FALLIBLE_IMPL_FROM_INFO,
+    crate::float_literal::EXCESSIVE_PRECISION_INFO,
+    crate::float_literal::LOSSY_FLOAT_LITERAL_INFO,
+    crate::floating_point_arithmetic::IMPRECISE_FLOPS_INFO,
+    crate::floating_point_arithmetic::SUBOPTIMAL_FLOPS_INFO,
+    crate::format::USELESS_FORMAT_INFO,
+    crate::format_args::FORMAT_IN_FORMAT_ARGS_INFO,
+    crate::format_args::TO_STRING_IN_FORMAT_ARGS_INFO,
+    crate::format_args::UNINLINED_FORMAT_ARGS_INFO,
+    crate::format_args::UNUSED_FORMAT_SPECS_INFO,
+    crate::format_impl::PRINT_IN_FORMAT_IMPL_INFO,
+    crate::format_impl::RECURSIVE_FORMAT_IMPL_INFO,
+    crate::format_push_string::FORMAT_PUSH_STRING_INFO,
+    crate::formatting::POSSIBLE_MISSING_COMMA_INFO,
+    crate::formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING_INFO,
+    crate::formatting::SUSPICIOUS_ELSE_FORMATTING_INFO,
+    crate::formatting::SUSPICIOUS_UNARY_OP_FORMATTING_INFO,
+    crate::from_over_into::FROM_OVER_INTO_INFO,
+    crate::from_raw_with_void_ptr::FROM_RAW_WITH_VOID_PTR_INFO,
+    crate::from_str_radix_10::FROM_STR_RADIX_10_INFO,
+    crate::functions::DOUBLE_MUST_USE_INFO,
+    crate::functions::MUST_USE_CANDIDATE_INFO,
+    crate::functions::MUST_USE_UNIT_INFO,
+    crate::functions::NOT_UNSAFE_PTR_ARG_DEREF_INFO,
+    crate::functions::RESULT_LARGE_ERR_INFO,
+    crate::functions::RESULT_UNIT_ERR_INFO,
+    crate::functions::TOO_MANY_ARGUMENTS_INFO,
+    crate::functions::TOO_MANY_LINES_INFO,
+    crate::future_not_send::FUTURE_NOT_SEND_INFO,
+    crate::if_let_mutex::IF_LET_MUTEX_INFO,
+    crate::if_not_else::IF_NOT_ELSE_INFO,
+    crate::if_then_some_else_none::IF_THEN_SOME_ELSE_NONE_INFO,
+    crate::implicit_hasher::IMPLICIT_HASHER_INFO,
+    crate::implicit_return::IMPLICIT_RETURN_INFO,
+    crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO,
+    crate::implicit_saturating_sub::IMPLICIT_SATURATING_SUB_INFO,
+    crate::inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR_INFO,
+    crate::index_refutable_slice::INDEX_REFUTABLE_SLICE_INFO,
+    crate::indexing_slicing::INDEXING_SLICING_INFO,
+    crate::indexing_slicing::OUT_OF_BOUNDS_INDEXING_INFO,
+    crate::infinite_iter::INFINITE_ITER_INFO,
+    crate::infinite_iter::MAYBE_INFINITE_ITER_INFO,
+    crate::inherent_impl::MULTIPLE_INHERENT_IMPL_INFO,
+    crate::inherent_to_string::INHERENT_TO_STRING_INFO,
+    crate::inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY_INFO,
+    crate::init_numbered_fields::INIT_NUMBERED_FIELDS_INFO,
+    crate::inline_fn_without_body::INLINE_FN_WITHOUT_BODY_INFO,
+    crate::instant_subtraction::MANUAL_INSTANT_ELAPSED_INFO,
+    crate::instant_subtraction::UNCHECKED_DURATION_SUBTRACTION_INFO,
+    crate::int_plus_one::INT_PLUS_ONE_INFO,
+    crate::invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS_INFO,
+    crate::invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED_INFO,
+    crate::items_after_statements::ITEMS_AFTER_STATEMENTS_INFO,
+    crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO,
+    crate::large_const_arrays::LARGE_CONST_ARRAYS_INFO,
+    crate::large_enum_variant::LARGE_ENUM_VARIANT_INFO,
+    crate::large_include_file::LARGE_INCLUDE_FILE_INFO,
+    crate::large_stack_arrays::LARGE_STACK_ARRAYS_INFO,
+    crate::len_zero::COMPARISON_TO_EMPTY_INFO,
+    crate::len_zero::LEN_WITHOUT_IS_EMPTY_INFO,
+    crate::len_zero::LEN_ZERO_INFO,
+    crate::let_if_seq::USELESS_LET_IF_SEQ_INFO,
+    crate::let_underscore::LET_UNDERSCORE_FUTURE_INFO,
+    crate::let_underscore::LET_UNDERSCORE_LOCK_INFO,
+    crate::let_underscore::LET_UNDERSCORE_MUST_USE_INFO,
+    crate::lifetimes::EXTRA_UNUSED_LIFETIMES_INFO,
+    crate::lifetimes::NEEDLESS_LIFETIMES_INFO,
+    crate::literal_representation::DECIMAL_LITERAL_REPRESENTATION_INFO,
+    crate::literal_representation::INCONSISTENT_DIGIT_GROUPING_INFO,
+    crate::literal_representation::LARGE_DIGIT_GROUPS_INFO,
+    crate::literal_representation::MISTYPED_LITERAL_SUFFIXES_INFO,
+    crate::literal_representation::UNREADABLE_LITERAL_INFO,
+    crate::literal_representation::UNUSUAL_BYTE_GROUPINGS_INFO,
+    crate::loops::EMPTY_LOOP_INFO,
+    crate::loops::EXPLICIT_COUNTER_LOOP_INFO,
+    crate::loops::EXPLICIT_INTO_ITER_LOOP_INFO,
+    crate::loops::EXPLICIT_ITER_LOOP_INFO,
+    crate::loops::FOR_KV_MAP_INFO,
+    crate::loops::ITER_NEXT_LOOP_INFO,
+    crate::loops::MANUAL_FIND_INFO,
+    crate::loops::MANUAL_FLATTEN_INFO,
+    crate::loops::MANUAL_MEMCPY_INFO,
+    crate::loops::MISSING_SPIN_LOOP_INFO,
+    crate::loops::MUT_RANGE_BOUND_INFO,
+    crate::loops::NEEDLESS_RANGE_LOOP_INFO,
+    crate::loops::NEVER_LOOP_INFO,
+    crate::loops::SAME_ITEM_PUSH_INFO,
+    crate::loops::SINGLE_ELEMENT_LOOP_INFO,
+    crate::loops::WHILE_IMMUTABLE_CONDITION_INFO,
+    crate::loops::WHILE_LET_LOOP_INFO,
+    crate::loops::WHILE_LET_ON_ITERATOR_INFO,
+    crate::macro_use::MACRO_USE_IMPORTS_INFO,
+    crate::main_recursion::MAIN_RECURSION_INFO,
+    crate::manual_assert::MANUAL_ASSERT_INFO,
+    crate::manual_async_fn::MANUAL_ASYNC_FN_INFO,
+    crate::manual_bits::MANUAL_BITS_INFO,
+    crate::manual_clamp::MANUAL_CLAMP_INFO,
+    crate::manual_is_ascii_check::MANUAL_IS_ASCII_CHECK_INFO,
+    crate::manual_let_else::MANUAL_LET_ELSE_INFO,
+    crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO,
+    crate::manual_rem_euclid::MANUAL_REM_EUCLID_INFO,
+    crate::manual_retain::MANUAL_RETAIN_INFO,
+    crate::manual_string_new::MANUAL_STRING_NEW_INFO,
+    crate::manual_strip::MANUAL_STRIP_INFO,
+    crate::map_unit_fn::OPTION_MAP_UNIT_FN_INFO,
+    crate::map_unit_fn::RESULT_MAP_UNIT_FN_INFO,
+    crate::match_result_ok::MATCH_RESULT_OK_INFO,
+    crate::matches::COLLAPSIBLE_MATCH_INFO,
+    crate::matches::INFALLIBLE_DESTRUCTURING_MATCH_INFO,
+    crate::matches::MANUAL_FILTER_INFO,
+    crate::matches::MANUAL_MAP_INFO,
+    crate::matches::MANUAL_UNWRAP_OR_INFO,
+    crate::matches::MATCH_AS_REF_INFO,
+    crate::matches::MATCH_BOOL_INFO,
+    crate::matches::MATCH_LIKE_MATCHES_MACRO_INFO,
+    crate::matches::MATCH_ON_VEC_ITEMS_INFO,
+    crate::matches::MATCH_OVERLAPPING_ARM_INFO,
+    crate::matches::MATCH_REF_PATS_INFO,
+    crate::matches::MATCH_SAME_ARMS_INFO,
+    crate::matches::MATCH_SINGLE_BINDING_INFO,
+    crate::matches::MATCH_STR_CASE_MISMATCH_INFO,
+    crate::matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS_INFO,
+    crate::matches::MATCH_WILD_ERR_ARM_INFO,
+    crate::matches::NEEDLESS_MATCH_INFO,
+    crate::matches::REDUNDANT_PATTERN_MATCHING_INFO,
+    crate::matches::REST_PAT_IN_FULLY_BOUND_STRUCTS_INFO,
+    crate::matches::SIGNIFICANT_DROP_IN_SCRUTINEE_INFO,
+    crate::matches::SINGLE_MATCH_INFO,
+    crate::matches::SINGLE_MATCH_ELSE_INFO,
+    crate::matches::TRY_ERR_INFO,
+    crate::matches::WILDCARD_ENUM_MATCH_ARM_INFO,
+    crate::matches::WILDCARD_IN_OR_PATTERNS_INFO,
+    crate::mem_forget::MEM_FORGET_INFO,
+    crate::mem_replace::MEM_REPLACE_OPTION_WITH_NONE_INFO,
+    crate::mem_replace::MEM_REPLACE_WITH_DEFAULT_INFO,
+    crate::mem_replace::MEM_REPLACE_WITH_UNINIT_INFO,
+    crate::methods::BIND_INSTEAD_OF_MAP_INFO,
+    crate::methods::BYTES_COUNT_TO_LEN_INFO,
+    crate::methods::BYTES_NTH_INFO,
+    crate::methods::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS_INFO,
+    crate::methods::CHARS_LAST_CMP_INFO,
+    crate::methods::CHARS_NEXT_CMP_INFO,
+    crate::methods::CLONED_INSTEAD_OF_COPIED_INFO,
+    crate::methods::CLONE_DOUBLE_REF_INFO,
+    crate::methods::CLONE_ON_COPY_INFO,
+    crate::methods::CLONE_ON_REF_PTR_INFO,
+    crate::methods::COLLAPSIBLE_STR_REPLACE_INFO,
+    crate::methods::ERR_EXPECT_INFO,
+    crate::methods::EXPECT_FUN_CALL_INFO,
+    crate::methods::EXPECT_USED_INFO,
+    crate::methods::EXTEND_WITH_DRAIN_INFO,
+    crate::methods::FILETYPE_IS_FILE_INFO,
+    crate::methods::FILTER_MAP_IDENTITY_INFO,
+    crate::methods::FILTER_MAP_NEXT_INFO,
+    crate::methods::FILTER_NEXT_INFO,
+    crate::methods::FLAT_MAP_IDENTITY_INFO,
+    crate::methods::FLAT_MAP_OPTION_INFO,
+    crate::methods::FROM_ITER_INSTEAD_OF_COLLECT_INFO,
+    crate::methods::GET_FIRST_INFO,
+    crate::methods::GET_LAST_WITH_LEN_INFO,
+    crate::methods::GET_UNWRAP_INFO,
+    crate::methods::IMPLICIT_CLONE_INFO,
+    crate::methods::INEFFICIENT_TO_STRING_INFO,
+    crate::methods::INSPECT_FOR_EACH_INFO,
+    crate::methods::INTO_ITER_ON_REF_INFO,
+    crate::methods::IS_DIGIT_ASCII_RADIX_INFO,
+    crate::methods::ITERATOR_STEP_BY_ZERO_INFO,
+    crate::methods::ITER_CLONED_COLLECT_INFO,
+    crate::methods::ITER_COUNT_INFO,
+    crate::methods::ITER_KV_MAP_INFO,
+    crate::methods::ITER_NEXT_SLICE_INFO,
+    crate::methods::ITER_NTH_INFO,
+    crate::methods::ITER_NTH_ZERO_INFO,
+    crate::methods::ITER_ON_EMPTY_COLLECTIONS_INFO,
+    crate::methods::ITER_ON_SINGLE_ITEMS_INFO,
+    crate::methods::ITER_OVEREAGER_CLONED_INFO,
+    crate::methods::ITER_SKIP_NEXT_INFO,
+    crate::methods::ITER_WITH_DRAIN_INFO,
+    crate::methods::MANUAL_FILTER_MAP_INFO,
+    crate::methods::MANUAL_FIND_MAP_INFO,
+    crate::methods::MANUAL_OK_OR_INFO,
+    crate::methods::MANUAL_SATURATING_ARITHMETIC_INFO,
+    crate::methods::MANUAL_SPLIT_ONCE_INFO,
+    crate::methods::MANUAL_STR_REPEAT_INFO,
+    crate::methods::MAP_CLONE_INFO,
+    crate::methods::MAP_COLLECT_RESULT_UNIT_INFO,
+    crate::methods::MAP_ERR_IGNORE_INFO,
+    crate::methods::MAP_FLATTEN_INFO,
+    crate::methods::MAP_IDENTITY_INFO,
+    crate::methods::MAP_UNWRAP_OR_INFO,
+    crate::methods::MUT_MUTEX_LOCK_INFO,
+    crate::methods::NAIVE_BYTECOUNT_INFO,
+    crate::methods::NEEDLESS_COLLECT_INFO,
+    crate::methods::NEEDLESS_OPTION_AS_DEREF_INFO,
+    crate::methods::NEEDLESS_OPTION_TAKE_INFO,
+    crate::methods::NEEDLESS_SPLITN_INFO,
+    crate::methods::NEW_RET_NO_SELF_INFO,
+    crate::methods::NONSENSICAL_OPEN_OPTIONS_INFO,
+    crate::methods::NO_EFFECT_REPLACE_INFO,
+    crate::methods::OBFUSCATED_IF_ELSE_INFO,
+    crate::methods::OK_EXPECT_INFO,
+    crate::methods::OPTION_AS_REF_DEREF_INFO,
+    crate::methods::OPTION_FILTER_MAP_INFO,
+    crate::methods::OPTION_MAP_OR_NONE_INFO,
+    crate::methods::OR_FUN_CALL_INFO,
+    crate::methods::OR_THEN_UNWRAP_INFO,
+    crate::methods::PATH_BUF_PUSH_OVERWRITE_INFO,
+    crate::methods::RANGE_ZIP_WITH_LEN_INFO,
+    crate::methods::REPEAT_ONCE_INFO,
+    crate::methods::RESULT_MAP_OR_INTO_OPTION_INFO,
+    crate::methods::SEARCH_IS_SOME_INFO,
+    crate::methods::SEEK_FROM_CURRENT_INFO,
+    crate::methods::SEEK_TO_START_INSTEAD_OF_REWIND_INFO,
+    crate::methods::SHOULD_IMPLEMENT_TRAIT_INFO,
+    crate::methods::SINGLE_CHAR_ADD_STR_INFO,
+    crate::methods::SINGLE_CHAR_PATTERN_INFO,
+    crate::methods::SKIP_WHILE_NEXT_INFO,
+    crate::methods::STABLE_SORT_PRIMITIVE_INFO,
+    crate::methods::STRING_EXTEND_CHARS_INFO,
+    crate::methods::SUSPICIOUS_MAP_INFO,
+    crate::methods::SUSPICIOUS_SPLITN_INFO,
+    crate::methods::SUSPICIOUS_TO_OWNED_INFO,
+    crate::methods::UNINIT_ASSUMED_INIT_INFO,
+    crate::methods::UNIT_HASH_INFO,
+    crate::methods::UNNECESSARY_FILTER_MAP_INFO,
+    crate::methods::UNNECESSARY_FIND_MAP_INFO,
+    crate::methods::UNNECESSARY_FOLD_INFO,
+    crate::methods::UNNECESSARY_JOIN_INFO,
+    crate::methods::UNNECESSARY_LAZY_EVALUATIONS_INFO,
+    crate::methods::UNNECESSARY_SORT_BY_INFO,
+    crate::methods::UNNECESSARY_TO_OWNED_INFO,
+    crate::methods::UNWRAP_OR_ELSE_DEFAULT_INFO,
+    crate::methods::UNWRAP_USED_INFO,
+    crate::methods::USELESS_ASREF_INFO,
+    crate::methods::VEC_RESIZE_TO_ZERO_INFO,
+    crate::methods::VERBOSE_FILE_READS_INFO,
+    crate::methods::WRONG_SELF_CONVENTION_INFO,
+    crate::methods::ZST_OFFSET_INFO,
+    crate::minmax::MIN_MAX_INFO,
+    crate::misc::SHORT_CIRCUIT_STATEMENT_INFO,
+    crate::misc::TOPLEVEL_REF_ARG_INFO,
+    crate::misc::USED_UNDERSCORE_BINDING_INFO,
+    crate::misc::ZERO_PTR_INFO,
+    crate::misc_early::BUILTIN_TYPE_SHADOW_INFO,
+    crate::misc_early::DOUBLE_NEG_INFO,
+    crate::misc_early::DUPLICATE_UNDERSCORE_ARGUMENT_INFO,
+    crate::misc_early::MIXED_CASE_HEX_LITERALS_INFO,
+    crate::misc_early::REDUNDANT_PATTERN_INFO,
+    crate::misc_early::SEPARATED_LITERAL_SUFFIX_INFO,
+    crate::misc_early::UNNEEDED_FIELD_PATTERN_INFO,
+    crate::misc_early::UNNEEDED_WILDCARD_PATTERN_INFO,
+    crate::misc_early::UNSEPARATED_LITERAL_SUFFIX_INFO,
+    crate::misc_early::ZERO_PREFIXED_LITERAL_INFO,
+    crate::mismatching_type_param_order::MISMATCHING_TYPE_PARAM_ORDER_INFO,
+    crate::missing_const_for_fn::MISSING_CONST_FOR_FN_INFO,
+    crate::missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS_INFO,
+    crate::missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES_INFO,
+    crate::missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS_INFO,
+    crate::missing_trait_methods::MISSING_TRAIT_METHODS_INFO,
+    crate::mixed_read_write_in_expression::DIVERGING_SUB_EXPRESSION_INFO,
+    crate::mixed_read_write_in_expression::MIXED_READ_WRITE_IN_EXPRESSION_INFO,
+    crate::module_style::MOD_MODULE_FILES_INFO,
+    crate::module_style::SELF_NAMED_MODULE_FILES_INFO,
+    crate::multi_assignments::MULTI_ASSIGNMENTS_INFO,
+    crate::mut_key::MUTABLE_KEY_TYPE_INFO,
+    crate::mut_mut::MUT_MUT_INFO,
+    crate::mut_reference::UNNECESSARY_MUT_PASSED_INFO,
+    crate::mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL_INFO,
+    crate::mutex_atomic::MUTEX_ATOMIC_INFO,
+    crate::mutex_atomic::MUTEX_INTEGER_INFO,
+    crate::needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE_INFO,
+    crate::needless_bool::BOOL_COMPARISON_INFO,
+    crate::needless_bool::NEEDLESS_BOOL_INFO,
+    crate::needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE_INFO,
+    crate::needless_continue::NEEDLESS_CONTINUE_INFO,
+    crate::needless_for_each::NEEDLESS_FOR_EACH_INFO,
+    crate::needless_late_init::NEEDLESS_LATE_INIT_INFO,
+    crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO,
+    crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO,
+    crate::needless_question_mark::NEEDLESS_QUESTION_MARK_INFO,
+    crate::needless_update::NEEDLESS_UPDATE_INFO,
+    crate::neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD_INFO,
+    crate::neg_multiply::NEG_MULTIPLY_INFO,
+    crate::new_without_default::NEW_WITHOUT_DEFAULT_INFO,
+    crate::no_effect::NO_EFFECT_INFO,
+    crate::no_effect::NO_EFFECT_UNDERSCORE_BINDING_INFO,
+    crate::no_effect::UNNECESSARY_OPERATION_INFO,
+    crate::non_copy_const::BORROW_INTERIOR_MUTABLE_CONST_INFO,
+    crate::non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST_INFO,
+    crate::non_expressive_names::JUST_UNDERSCORES_AND_DIGITS_INFO,
+    crate::non_expressive_names::MANY_SINGLE_CHAR_NAMES_INFO,
+    crate::non_expressive_names::SIMILAR_NAMES_INFO,
+    crate::non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS_INFO,
+    crate::non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY_INFO,
+    crate::nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES_INFO,
+    crate::octal_escapes::OCTAL_ESCAPES_INFO,
+    crate::only_used_in_recursion::ONLY_USED_IN_RECURSION_INFO,
+    crate::operators::ABSURD_EXTREME_COMPARISONS_INFO,
+    crate::operators::ARITHMETIC_SIDE_EFFECTS_INFO,
+    crate::operators::ASSIGN_OP_PATTERN_INFO,
+    crate::operators::BAD_BIT_MASK_INFO,
+    crate::operators::CMP_NAN_INFO,
+    crate::operators::CMP_OWNED_INFO,
+    crate::operators::DOUBLE_COMPARISONS_INFO,
+    crate::operators::DURATION_SUBSEC_INFO,
+    crate::operators::EQ_OP_INFO,
+    crate::operators::ERASING_OP_INFO,
+    crate::operators::FLOAT_ARITHMETIC_INFO,
+    crate::operators::FLOAT_CMP_INFO,
+    crate::operators::FLOAT_CMP_CONST_INFO,
+    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,
+    crate::operators::MODULO_ONE_INFO,
+    crate::operators::NEEDLESS_BITWISE_BOOL_INFO,
+    crate::operators::OP_REF_INFO,
+    crate::operators::PTR_EQ_INFO,
+    crate::operators::SELF_ASSIGNMENT_INFO,
+    crate::operators::VERBOSE_BIT_MASK_INFO,
+    crate::option_env_unwrap::OPTION_ENV_UNWRAP_INFO,
+    crate::option_if_let_else::OPTION_IF_LET_ELSE_INFO,
+    crate::overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL_INFO,
+    crate::panic_in_result_fn::PANIC_IN_RESULT_FN_INFO,
+    crate::panic_unimplemented::PANIC_INFO,
+    crate::panic_unimplemented::TODO_INFO,
+    crate::panic_unimplemented::UNIMPLEMENTED_INFO,
+    crate::panic_unimplemented::UNREACHABLE_INFO,
+    crate::partial_pub_fields::PARTIAL_PUB_FIELDS_INFO,
+    crate::partialeq_ne_impl::PARTIALEQ_NE_IMPL_INFO,
+    crate::partialeq_to_none::PARTIALEQ_TO_NONE_INFO,
+    crate::pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE_INFO,
+    crate::pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF_INFO,
+    crate::pattern_type_mismatch::PATTERN_TYPE_MISMATCH_INFO,
+    crate::precedence::PRECEDENCE_INFO,
+    crate::ptr::CMP_NULL_INFO,
+    crate::ptr::INVALID_NULL_PTR_USAGE_INFO,
+    crate::ptr::MUT_FROM_REF_INFO,
+    crate::ptr::PTR_ARG_INFO,
+    crate::ptr_offset_with_cast::PTR_OFFSET_WITH_CAST_INFO,
+    crate::pub_use::PUB_USE_INFO,
+    crate::question_mark::QUESTION_MARK_INFO,
+    crate::ranges::MANUAL_RANGE_CONTAINS_INFO,
+    crate::ranges::RANGE_MINUS_ONE_INFO,
+    crate::ranges::RANGE_PLUS_ONE_INFO,
+    crate::ranges::REVERSED_EMPTY_RANGES_INFO,
+    crate::rc_clone_in_vec_init::RC_CLONE_IN_VEC_INIT_INFO,
+    crate::read_zero_byte_vec::READ_ZERO_BYTE_VEC_INFO,
+    crate::redundant_clone::REDUNDANT_CLONE_INFO,
+    crate::redundant_closure_call::REDUNDANT_CLOSURE_CALL_INFO,
+    crate::redundant_else::REDUNDANT_ELSE_INFO,
+    crate::redundant_field_names::REDUNDANT_FIELD_NAMES_INFO,
+    crate::redundant_pub_crate::REDUNDANT_PUB_CRATE_INFO,
+    crate::redundant_slicing::DEREF_BY_SLICING_INFO,
+    crate::redundant_slicing::REDUNDANT_SLICING_INFO,
+    crate::redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES_INFO,
+    crate::ref_option_ref::REF_OPTION_REF_INFO,
+    crate::reference::DEREF_ADDROF_INFO,
+    crate::regex::INVALID_REGEX_INFO,
+    crate::regex::TRIVIAL_REGEX_INFO,
+    crate::return_self_not_must_use::RETURN_SELF_NOT_MUST_USE_INFO,
+    crate::returns::LET_AND_RETURN_INFO,
+    crate::returns::NEEDLESS_RETURN_INFO,
+    crate::same_name_method::SAME_NAME_METHOD_INFO,
+    crate::self_named_constructors::SELF_NAMED_CONSTRUCTORS_INFO,
+    crate::semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED_INFO,
+    crate::serde_api::SERDE_API_MISUSE_INFO,
+    crate::shadow::SHADOW_REUSE_INFO,
+    crate::shadow::SHADOW_SAME_INFO,
+    crate::shadow::SHADOW_UNRELATED_INFO,
+    crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO,
+    crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO,
+    crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO,
+    crate::slow_vector_initialization::SLOW_VECTOR_INITIALIZATION_INFO,
+    crate::std_instead_of_core::ALLOC_INSTEAD_OF_CORE_INFO,
+    crate::std_instead_of_core::STD_INSTEAD_OF_ALLOC_INFO,
+    crate::std_instead_of_core::STD_INSTEAD_OF_CORE_INFO,
+    crate::strings::STRING_ADD_INFO,
+    crate::strings::STRING_ADD_ASSIGN_INFO,
+    crate::strings::STRING_FROM_UTF8_AS_BYTES_INFO,
+    crate::strings::STRING_LIT_AS_BYTES_INFO,
+    crate::strings::STRING_SLICE_INFO,
+    crate::strings::STRING_TO_STRING_INFO,
+    crate::strings::STR_TO_STRING_INFO,
+    crate::strings::TRIM_SPLIT_WHITESPACE_INFO,
+    crate::strlen_on_c_strings::STRLEN_ON_C_STRINGS_INFO,
+    crate::suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS_INFO,
+    crate::suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL_INFO,
+    crate::suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL_INFO,
+    crate::suspicious_xor_used_as_pow::SUSPICIOUS_XOR_USED_AS_POW_INFO,
+    crate::swap::ALMOST_SWAPPED_INFO,
+    crate::swap::MANUAL_SWAP_INFO,
+    crate::swap_ptr_to_ref::SWAP_PTR_TO_REF_INFO,
+    crate::tabs_in_doc_comments::TABS_IN_DOC_COMMENTS_INFO,
+    crate::temporary_assignment::TEMPORARY_ASSIGNMENT_INFO,
+    crate::to_digit_is_some::TO_DIGIT_IS_SOME_INFO,
+    crate::trailing_empty_array::TRAILING_EMPTY_ARRAY_INFO,
+    crate::trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS_INFO,
+    crate::trait_bounds::TYPE_REPETITION_IN_BOUNDS_INFO,
+    crate::transmute::CROSSPOINTER_TRANSMUTE_INFO,
+    crate::transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS_INFO,
+    crate::transmute::TRANSMUTE_BYTES_TO_STR_INFO,
+    crate::transmute::TRANSMUTE_FLOAT_TO_INT_INFO,
+    crate::transmute::TRANSMUTE_INT_TO_BOOL_INFO,
+    crate::transmute::TRANSMUTE_INT_TO_CHAR_INFO,
+    crate::transmute::TRANSMUTE_INT_TO_FLOAT_INFO,
+    crate::transmute::TRANSMUTE_NUM_TO_BYTES_INFO,
+    crate::transmute::TRANSMUTE_PTR_TO_PTR_INFO,
+    crate::transmute::TRANSMUTE_PTR_TO_REF_INFO,
+    crate::transmute::TRANSMUTE_UNDEFINED_REPR_INFO,
+    crate::transmute::TRANSMUTING_NULL_INFO,
+    crate::transmute::UNSOUND_COLLECTION_TRANSMUTE_INFO,
+    crate::transmute::USELESS_TRANSMUTE_INFO,
+    crate::transmute::WRONG_TRANSMUTE_INFO,
+    crate::types::BORROWED_BOX_INFO,
+    crate::types::BOX_COLLECTION_INFO,
+    crate::types::LINKEDLIST_INFO,
+    crate::types::OPTION_OPTION_INFO,
+    crate::types::RC_BUFFER_INFO,
+    crate::types::RC_MUTEX_INFO,
+    crate::types::REDUNDANT_ALLOCATION_INFO,
+    crate::types::TYPE_COMPLEXITY_INFO,
+    crate::types::VEC_BOX_INFO,
+    crate::undocumented_unsafe_blocks::UNDOCUMENTED_UNSAFE_BLOCKS_INFO,
+    crate::unicode::INVISIBLE_CHARACTERS_INFO,
+    crate::unicode::NON_ASCII_LITERAL_INFO,
+    crate::unicode::UNICODE_NOT_NFC_INFO,
+    crate::uninit_vec::UNINIT_VEC_INFO,
+    crate::unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD_INFO,
+    crate::unit_types::LET_UNIT_VALUE_INFO,
+    crate::unit_types::UNIT_ARG_INFO,
+    crate::unit_types::UNIT_CMP_INFO,
+    crate::unnamed_address::FN_ADDRESS_COMPARISONS_INFO,
+    crate::unnamed_address::VTABLE_ADDRESS_COMPARISONS_INFO,
+    crate::unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS_INFO,
+    crate::unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS_INFO,
+    crate::unnecessary_wraps::UNNECESSARY_WRAPS_INFO,
+    crate::unnested_or_patterns::UNNESTED_OR_PATTERNS_INFO,
+    crate::unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME_INFO,
+    crate::unused_async::UNUSED_ASYNC_INFO,
+    crate::unused_io_amount::UNUSED_IO_AMOUNT_INFO,
+    crate::unused_peekable::UNUSED_PEEKABLE_INFO,
+    crate::unused_rounding::UNUSED_ROUNDING_INFO,
+    crate::unused_self::UNUSED_SELF_INFO,
+    crate::unused_unit::UNUSED_UNIT_INFO,
+    crate::unwrap::PANICKING_UNWRAP_INFO,
+    crate::unwrap::UNNECESSARY_UNWRAP_INFO,
+    crate::unwrap_in_result::UNWRAP_IN_RESULT_INFO,
+    crate::upper_case_acronyms::UPPER_CASE_ACRONYMS_INFO,
+    crate::use_self::USE_SELF_INFO,
+    crate::useless_conversion::USELESS_CONVERSION_INFO,
+    crate::vec::USELESS_VEC_INFO,
+    crate::vec_init_then_push::VEC_INIT_THEN_PUSH_INFO,
+    crate::wildcard_imports::ENUM_GLOB_USE_INFO,
+    crate::wildcard_imports::WILDCARD_IMPORTS_INFO,
+    crate::write::PRINTLN_EMPTY_STRING_INFO,
+    crate::write::PRINT_LITERAL_INFO,
+    crate::write::PRINT_STDERR_INFO,
+    crate::write::PRINT_STDOUT_INFO,
+    crate::write::PRINT_WITH_NEWLINE_INFO,
+    crate::write::USE_DEBUG_INFO,
+    crate::write::WRITELN_EMPTY_STRING_INFO,
+    crate::write::WRITE_LITERAL_INFO,
+    crate::write::WRITE_WITH_NEWLINE_INFO,
+    crate::zero_div_zero::ZERO_DIVIDED_BY_ZERO_INFO,
+    crate::zero_sized_map_values::ZERO_SIZED_MAP_VALUES_INFO,
+];
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index c4e7f8bfe1e..18e742a85b3 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -9,6 +9,7 @@ use clippy_utils::{
 };
 use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX};
 use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::graph::iterate::{CycleDetector, TriColorDepthFirstSearch};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_ty, Visitor};
 use rustc_hir::{
@@ -274,9 +275,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
         }
 
         let typeck = cx.typeck_results();
-        let (kind, sub_expr) = if let Some(x) = try_parse_ref_op(cx.tcx, typeck, expr) {
-            x
-        } else {
+        let Some((kind, sub_expr)) = try_parse_ref_op(cx.tcx, typeck, expr) else {
             // The whole chain of reference operations has been seen
             if let Some((state, data)) = self.state.take() {
                 report(cx, expr, state, data);
@@ -806,30 +805,39 @@ fn walk_parents<'tcx>(
                     .position(|arg| arg.hir_id == child_id)
                     .zip(expr_sig(cx, func))
                     .and_then(|(i, sig)| {
-                        sig.input_with_hir(i).map(|(hir_ty, ty)| match hir_ty {
-                            // Type inference for closures can depend on how they're called. Only go by the explicit
-                            // types here.
-                            Some(hir_ty) => binding_ty_auto_deref_stability(cx, hir_ty, precedence, ty.bound_vars()),
-                            None => {
-                                if let ty::Param(param_ty) = ty.skip_binder().kind() {
-                                    needless_borrow_impl_arg_position(
-                                        cx,
-                                        possible_borrowers,
-                                        parent,
-                                        i,
-                                        *param_ty,
-                                        e,
-                                        precedence,
-                                        msrv,
-                                    )
-                                } else {
-                                    ty_auto_deref_stability(cx, cx.tcx.erase_late_bound_regions(ty), precedence)
-                                        .position_for_arg()
-                                }
-                            },
+                        sig.input_with_hir(i).map(|(hir_ty, ty)| {
+                            match hir_ty {
+                                // Type inference for closures can depend on how they're called. Only go by the explicit
+                                // types here.
+                                Some(hir_ty) => {
+                                    binding_ty_auto_deref_stability(cx, hir_ty, precedence, ty.bound_vars())
+                                },
+                                None => {
+                                    // `e.hir_id == child_id` for https://github.com/rust-lang/rust-clippy/issues/9739
+                                    // `!call_is_qualified(func)` for https://github.com/rust-lang/rust-clippy/issues/9782
+                                    if e.hir_id == child_id
+                                        && !call_is_qualified(func)
+                                        && let ty::Param(param_ty) = ty.skip_binder().kind()
+                                    {
+                                        needless_borrow_impl_arg_position(
+                                            cx,
+                                            possible_borrowers,
+                                            parent,
+                                            i,
+                                            *param_ty,
+                                            e,
+                                            precedence,
+                                            msrv,
+                                        )
+                                    } else {
+                                        ty_auto_deref_stability(cx, cx.tcx.erase_late_bound_regions(ty), precedence)
+                                            .position_for_arg()
+                                    }
+                                },
+                            }
                         })
                     }),
-                ExprKind::MethodCall(_, receiver, args, _) => {
+                ExprKind::MethodCall(method, receiver, args, _) => {
                     let id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap();
                     if receiver.hir_id == child_id {
                         // Check for calls to trait methods where the trait is implemented on a reference.
@@ -863,7 +871,9 @@ fn walk_parents<'tcx>(
                     }
                     args.iter().position(|arg| arg.hir_id == child_id).map(|i| {
                         let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i + 1];
-                        if let ty::Param(param_ty) = ty.kind() {
+                        // `e.hir_id == child_id` for https://github.com/rust-lang/rust-clippy/issues/9739
+                        // `method.args.is_none()` for https://github.com/rust-lang/rust-clippy/issues/9782
+                        if e.hir_id == child_id && method.args.is_none() && let ty::Param(param_ty) = ty.kind() {
                             needless_borrow_impl_arg_position(
                                 cx,
                                 possible_borrowers,
@@ -1041,13 +1051,25 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
     v.0
 }
 
+fn call_is_qualified(expr: &Expr<'_>) -> bool {
+    if let ExprKind::Path(path) = &expr.kind {
+        match path {
+            QPath::Resolved(_, path) => path.segments.last().map_or(false, |segment| segment.args.is_some()),
+            QPath::TypeRelative(_, segment) => segment.args.is_some(),
+            QPath::LangItem(..) => false,
+        }
+    } else {
+        false
+    }
+}
+
 // Checks whether:
 // * child is an expression of the form `&e` in an argument position requiring an `impl Trait`
 // * `e`'s type implements `Trait` and is copyable
 // If the conditions are met, returns `Some(Position::ImplArg(..))`; otherwise, returns `None`.
 //   The "is copyable" condition is to avoid the case where removing the `&` means `e` would have to
 // be moved, but it cannot be.
-#[expect(clippy::too_many_arguments)]
+#[expect(clippy::too_many_arguments, clippy::too_many_lines)]
 fn needless_borrow_impl_arg_position<'tcx>(
     cx: &LateContext<'tcx>,
     possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
@@ -1109,6 +1131,16 @@ fn needless_borrow_impl_arg_position<'tcx>(
         return Position::Other(precedence);
     }
 
+    // See:
+    // - https://github.com/rust-lang/rust-clippy/pull/9674#issuecomment-1289294201
+    // - https://github.com/rust-lang/rust-clippy/pull/9674#issuecomment-1292225232
+    if projection_predicates
+        .iter()
+        .any(|projection_predicate| is_mixed_projection_predicate(cx, callee_def_id, projection_predicate))
+    {
+        return Position::Other(precedence);
+    }
+
     // `substs_with_referent_ty` can be constructed outside of `check_referent` because the same
     // elements are modified each time `check_referent` is called.
     let mut substs_with_referent_ty = substs_with_expr_ty.to_vec();
@@ -1188,6 +1220,37 @@ fn has_ref_mut_self_method(cx: &LateContext<'_>, trait_def_id: DefId) -> bool {
         })
 }
 
+fn is_mixed_projection_predicate<'tcx>(
+    cx: &LateContext<'tcx>,
+    callee_def_id: DefId,
+    projection_predicate: &ProjectionPredicate<'tcx>,
+) -> bool {
+    let generics = cx.tcx.generics_of(callee_def_id);
+    // The predicate requires the projected type to equal a type parameter from the parent context.
+    if let Some(term_ty) = projection_predicate.term.ty()
+        && let ty::Param(term_param_ty) = term_ty.kind()
+        && (term_param_ty.index as usize) < generics.parent_count
+    {
+        // The inner-most self type is a type parameter from the current function.
+        let mut projection_ty = projection_predicate.projection_ty;
+        loop {
+            match projection_ty.self_ty().kind() {
+                ty::Projection(inner_projection_ty) => {
+                    projection_ty = *inner_projection_ty;
+                }
+                ty::Param(param_ty) => {
+                    return (param_ty.index as usize) >= generics.parent_count;
+                }
+                _ => {
+                    return false;
+                }
+            }
+        }
+    } else {
+        false
+    }
+}
+
 fn referent_used_exactly_once<'tcx>(
     cx: &LateContext<'tcx>,
     possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
@@ -1199,6 +1262,8 @@ fn referent_used_exactly_once<'tcx>(
         && let Some(statement) = mir.basic_blocks[location.block].statements.get(location.statement_index)
         && let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind
         && !place.has_deref()
+        // Ensure not in a loop (https://github.com/rust-lang/rust-clippy/issues/9710)
+        && TriColorDepthFirstSearch::new(&mir.basic_blocks).run_from(location.block, &mut CycleDetector).is_none()
     {
         let body_owner_local_def_id = cx.tcx.hir().enclosing_body_owner(reference.hir_id);
         if possible_borrowers
@@ -1316,6 +1381,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
                 continue;
             },
             ty::Param(_) => TyPosition::new_deref_stable_for_result(precedence, ty),
+            ty::Projection(_) if ty.has_non_region_param() => TyPosition::new_deref_stable_for_result(precedence, ty),
             ty::Infer(_) | ty::Error(_) | ty::Bound(..) | ty::Opaque(..) | ty::Placeholder(_) | ty::Dynamic(..) => {
                 Position::ReborrowStable(precedence).into()
             },
@@ -1342,11 +1408,9 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
             | ty::Closure(..)
             | ty::Never
             | ty::Tuple(_)
-            | ty::Projection(_) => Position::DerefStable(
-                precedence,
-                ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
-            )
-            .into(),
+            | ty::Projection(_) => {
+                Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds())).into()
+            },
         };
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
index 5ab7144e290..68122b4cef5 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::macro_backtrace;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::def::{Namespace, Res};
 use rustc_hir::def_id::DefIdMap;
 use rustc_hir::{Expr, ForeignItem, HirId, ImplItem, Item, Pat, Path, Stmt, TraitItem, Ty};
 use rustc_lint::{LateContext, LateLintPass};
@@ -89,7 +88,7 @@ impl DisallowedMacros {
                     &format!("use of a disallowed macro `{}`", conf.path()),
                     |diag| {
                         if let Some(reason) = conf.reason() {
-                            diag.note(&format!("{reason} (from clippy.toml)"));
+                            diag.note(reason);
                         }
                     },
                 );
@@ -104,7 +103,7 @@ impl LateLintPass<'_> for DisallowedMacros {
     fn check_crate(&mut self, cx: &LateContext<'_>) {
         for (index, conf) in self.conf_disallowed.iter().enumerate() {
             let segs: Vec<_> = conf.path().split("::").collect();
-            if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, Some(Namespace::MacroNS)) {
+            for id in clippy_utils::def_path_def_ids(cx, &segs) {
                 self.disallowed.insert(id, index);
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
index 6ac85606d9c..ca8671c8f1a 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::{fn_def_id, get_parent_expr, path_def_id};
 
-use rustc_hir::def::{Namespace, Res};
 use rustc_hir::def_id::DefIdMap;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -79,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods {
     fn check_crate(&mut self, cx: &LateContext<'_>) {
         for (index, conf) in self.conf_disallowed.iter().enumerate() {
             let segs: Vec<_> = conf.path().split("::").collect();
-            if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, Some(Namespace::ValueNS)) {
+            for id in clippy_utils::def_path_def_ids(cx, &segs) {
                 self.disallowed.insert(id, index);
             }
         }
@@ -104,7 +103,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods {
         let msg = format!("use of a disallowed method `{}`", conf.path());
         span_lint_and_then(cx, DISALLOWED_METHODS, expr.span, &msg, |diag| {
             if let Some(reason) = conf.reason() {
-                diag.note(&format!("{reason} (from clippy.toml)"));
+                diag.note(reason);
             }
         });
     }
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_types.rs b/src/tools/clippy/clippy_lints/src/disallowed_types.rs
index c7131fc164d..aee3d8c4f08 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_types.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_types.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def::{Namespace, Res};
+use rustc_hir::def::Res;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -53,8 +53,8 @@ declare_clippy_lint! {
 #[derive(Clone, Debug)]
 pub struct DisallowedTypes {
     conf_disallowed: Vec<conf::DisallowedPath>,
-    def_ids: FxHashMap<DefId, Option<String>>,
-    prim_tys: FxHashMap<PrimTy, Option<String>>,
+    def_ids: FxHashMap<DefId, usize>,
+    prim_tys: FxHashMap<PrimTy, usize>,
 }
 
 impl DisallowedTypes {
@@ -69,13 +69,13 @@ impl DisallowedTypes {
     fn check_res_emit(&self, cx: &LateContext<'_>, res: &Res, span: Span) {
         match res {
             Res::Def(_, did) => {
-                if let Some(reason) = self.def_ids.get(did) {
-                    emit(cx, &cx.tcx.def_path_str(*did), span, reason.as_deref());
+                if let Some(&index) = self.def_ids.get(did) {
+                    emit(cx, &cx.tcx.def_path_str(*did), span, &self.conf_disallowed[index]);
                 }
             },
             Res::PrimTy(prim) => {
-                if let Some(reason) = self.prim_tys.get(prim) {
-                    emit(cx, prim.name_str(), span, reason.as_deref());
+                if let Some(&index) = self.prim_tys.get(prim) {
+                    emit(cx, prim.name_str(), span, &self.conf_disallowed[index]);
                 }
             },
             _ => {},
@@ -87,17 +87,19 @@ impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]);
 
 impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
     fn check_crate(&mut self, cx: &LateContext<'_>) {
-        for conf in &self.conf_disallowed {
+        for (index, conf) in self.conf_disallowed.iter().enumerate() {
             let segs: Vec<_> = conf.path().split("::").collect();
-            let reason = conf.reason().map(|reason| format!("{reason} (from clippy.toml)"));
-            match clippy_utils::def_path_res(cx, &segs, Some(Namespace::TypeNS)) {
-                Res::Def(_, id) => {
-                    self.def_ids.insert(id, reason);
-                },
-                Res::PrimTy(ty) => {
-                    self.prim_tys.insert(ty, reason);
-                },
-                _ => {},
+
+            for res in clippy_utils::def_path_res(cx, &segs) {
+                match res {
+                    Res::Def(_, id) => {
+                        self.def_ids.insert(id, index);
+                    },
+                    Res::PrimTy(ty) => {
+                        self.prim_tys.insert(ty, index);
+                    },
+                    _ => {},
+                }
             }
         }
     }
@@ -119,14 +121,14 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
     }
 }
 
-fn emit(cx: &LateContext<'_>, name: &str, span: Span, reason: Option<&str>) {
+fn emit(cx: &LateContext<'_>, name: &str, span: Span, conf: &conf::DisallowedPath) {
     span_lint_and_then(
         cx,
         DISALLOWED_TYPES,
         span,
         &format!("`{name}` is not allowed according to config"),
         |diag| {
-            if let Some(reason) = reason {
+            if let Some(reason) = conf.reason() {
                 diag.note(reason);
             }
         },
diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs
index daaab79fef9..ae5f9424b23 100644
--- a/src/tools/clippy/clippy_lints/src/doc.rs
+++ b/src/tools/clippy/clippy_lints/src/doc.rs
@@ -11,7 +11,7 @@ use rustc_ast::token::CommentKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::emitter::EmitterWriter;
-use rustc_errors::{Applicability, Handler, MultiSpan, SuggestionStyle};
+use rustc_errors::{Applicability, Handler, SuggestionStyle};
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{AnonConst, Expr};
@@ -221,6 +221,42 @@ declare_clippy_lint! {
     "possible typo for an intra-doc link"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for the doc comments of publicly visible
+    /// safe functions and traits and warns if there is a `# Safety` section.
+    ///
+    /// ### Why is this bad?
+    /// Safe functions and traits are safe to implement and therefore do not
+    /// need to describe safety preconditions that users are required to uphold.
+    ///
+    /// ### Examples
+    /// ```rust
+    ///# type Universe = ();
+    /// /// # Safety
+    /// ///
+    /// /// This function should not be called before the horsemen are ready.
+    /// pub fn start_apocalypse_but_safely(u: &mut Universe) {
+    ///     unimplemented!();
+    /// }
+    /// ```
+    ///
+    /// The function is safe, so there shouldn't be any preconditions
+    /// that have to be explained for safety reasons.
+    ///
+    /// ```rust
+    ///# type Universe = ();
+    /// /// This function should really be documented
+    /// pub fn start_apocalypse(u: &mut Universe) {
+    ///     unimplemented!();
+    /// }
+    /// ```
+    #[clippy::version = "1.66.0"]
+    pub UNNECESSARY_SAFETY_DOC,
+    style,
+    "`pub fn` or `pub trait` with `# Safety` docs"
+}
+
 #[expect(clippy::module_name_repetitions)]
 #[derive(Clone)]
 pub struct DocMarkdown {
@@ -243,7 +279,8 @@ impl_lint_pass!(DocMarkdown => [
     MISSING_SAFETY_DOC,
     MISSING_ERRORS_DOC,
     MISSING_PANICS_DOC,
-    NEEDLESS_DOCTEST_MAIN
+    NEEDLESS_DOCTEST_MAIN,
+    UNNECESSARY_SAFETY_DOC,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
@@ -254,7 +291,7 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
 
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
         let attrs = cx.tcx.hir().attrs(item.hir_id());
-        let headers = check_attrs(cx, &self.valid_idents, attrs);
+        let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else { return };
         match item.kind {
             hir::ItemKind::Fn(ref sig, _, body_id) => {
                 if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) {
@@ -265,29 +302,26 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
                         panic_span: None,
                     };
                     fpu.visit_expr(body.value);
-                    lint_for_missing_headers(
-                        cx,
-                        item.owner_id.def_id,
-                        item.span,
-                        sig,
-                        headers,
-                        Some(body_id),
-                        fpu.panic_span,
-                    );
+                    lint_for_missing_headers(cx, item.owner_id.def_id, sig, headers, Some(body_id), fpu.panic_span);
                 }
             },
             hir::ItemKind::Impl(impl_) => {
                 self.in_trait_impl = impl_.of_trait.is_some();
             },
-            hir::ItemKind::Trait(_, unsafety, ..) => {
-                if !headers.safety && unsafety == hir::Unsafety::Unsafe {
-                    span_lint(
-                        cx,
-                        MISSING_SAFETY_DOC,
-                        item.span,
-                        "docs for unsafe trait missing `# Safety` section",
-                    );
-                }
+            hir::ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) {
+                (false, hir::Unsafety::Unsafe) => span_lint(
+                    cx,
+                    MISSING_SAFETY_DOC,
+                    cx.tcx.def_span(item.owner_id),
+                    "docs for unsafe trait missing `# Safety` section",
+                ),
+                (true, hir::Unsafety::Normal) => span_lint(
+                    cx,
+                    UNNECESSARY_SAFETY_DOC,
+                    cx.tcx.def_span(item.owner_id),
+                    "docs for safe trait have unnecessary `# Safety` section",
+                ),
+                _ => (),
             },
             _ => (),
         }
@@ -301,17 +335,17 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
 
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
         let attrs = cx.tcx.hir().attrs(item.hir_id());
-        let headers = check_attrs(cx, &self.valid_idents, attrs);
+        let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else { return };
         if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
             if !in_external_macro(cx.tcx.sess, item.span) {
-                lint_for_missing_headers(cx, item.owner_id.def_id, item.span, sig, headers, None, None);
+                lint_for_missing_headers(cx, item.owner_id.def_id, sig, headers, None, None);
             }
         }
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
         let attrs = cx.tcx.hir().attrs(item.hir_id());
-        let headers = check_attrs(cx, &self.valid_idents, attrs);
+        let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else { return };
         if self.in_trait_impl || in_external_macro(cx.tcx.sess, item.span) {
             return;
         }
@@ -323,23 +357,14 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
                 panic_span: None,
             };
             fpu.visit_expr(body.value);
-            lint_for_missing_headers(
-                cx,
-                item.owner_id.def_id,
-                item.span,
-                sig,
-                headers,
-                Some(body_id),
-                fpu.panic_span,
-            );
+            lint_for_missing_headers(cx, item.owner_id.def_id, sig, headers, Some(body_id), fpu.panic_span);
         }
     }
 }
 
-fn lint_for_missing_headers<'tcx>(
-    cx: &LateContext<'tcx>,
+fn lint_for_missing_headers(
+    cx: &LateContext<'_>,
     def_id: LocalDefId,
-    span: impl Into<MultiSpan> + Copy,
     sig: &hir::FnSig<'_>,
     headers: DocHeaders,
     body_id: Option<hir::BodyId>,
@@ -359,13 +384,21 @@ fn lint_for_missing_headers<'tcx>(
         return;
     }
 
-    if !headers.safety && sig.header.unsafety == hir::Unsafety::Unsafe {
-        span_lint(
+    let span = cx.tcx.def_span(def_id);
+    match (headers.safety, sig.header.unsafety) {
+        (false, hir::Unsafety::Unsafe) => span_lint(
             cx,
             MISSING_SAFETY_DOC,
             span,
             "unsafe function's docs miss `# Safety` section",
-        );
+        ),
+        (true, hir::Unsafety::Normal) => span_lint(
+            cx,
+            UNNECESSARY_SAFETY_DOC,
+            span,
+            "safe function's docs have unnecessary `# Safety` section",
+        ),
+        _ => (),
     }
     if !headers.panics && panic_span.is_some() {
         span_lint_and_note(
@@ -394,9 +427,7 @@ fn lint_for_missing_headers<'tcx>(
                 let body = cx.tcx.hir().body(body_id);
                 let ret_ty = typeck.expr_ty(body.value);
                 if implements_trait(cx, ret_ty, future, &[]);
-                if let ty::Opaque(_, subs) = ret_ty.kind();
-                if let Some(gen) = subs.types().next();
-                if let ty::Generator(_, subs, _) = gen.kind();
+                if let ty::Generator(_, subs, _) = ret_ty.kind();
                 if is_type_diagnostic_item(cx, subs.as_generator().return_ty(), sym::Result);
                 then {
                     span_lint(
@@ -467,7 +498,7 @@ struct DocHeaders {
     panics: bool,
 }
 
-fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &'a [Attribute]) -> DocHeaders {
+fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[Attribute]) -> Option<DocHeaders> {
     use pulldown_cmark::{BrokenLink, CowStr, Options};
     /// We don't want the parser to choke on intra doc links. Since we don't
     /// actually care about rendering them, just pretend that all broken links are
@@ -488,11 +519,7 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs
         } else if attr.has_name(sym::doc) {
             // ignore mix of sugared and non-sugared doc
             // don't trigger the safety or errors check
-            return DocHeaders {
-                safety: true,
-                errors: true,
-                panics: true,
-            };
+            return None;
         }
     }
 
@@ -504,7 +531,7 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs
     }
 
     if doc.is_empty() {
-        return DocHeaders::default();
+        return Some(DocHeaders::default());
     }
 
     let mut cb = fake_broken_link_callback;
@@ -527,7 +554,7 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs
             (previous, current) => Err(((previous, previous_range), (current, current_range))),
         }
     });
-    check_doc(cx, valid_idents, events, &spans)
+    Some(check_doc(cx, valid_idents, events, &spans))
 }
 
 const RUST_CODE: &[&str] = &["rust", "no_run", "should_panic", "compile_fail"];
diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs
index 223545fa798..b77b5621b4c 100644
--- a/src/tools/clippy/clippy_lints/src/enum_variants.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs
@@ -250,7 +250,7 @@ impl LateLintPass<'_> for EnumVariantNames {
         let item_name = item.ident.name.as_str();
         let item_camel = to_camel_case(item_name);
         if !item.span.from_expansion() && is_present_in_source(cx, item.span) {
-            if let Some(&(ref mod_name, ref mod_camel)) = self.modules.last() {
+            if let Some((mod_name, mod_camel)) = self.modules.last() {
                 // constants don't have surrounding modules
                 if !mod_camel.is_empty() {
                     if mod_name == &item.ident.name {
diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
index b40cb7cddaf..c691e6c5402 100644
--- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
+++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::implements_trait;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Pat, PatKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -67,16 +66,14 @@ fn is_structural_partial_eq<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: T
 
 impl<'tcx> LateLintPass<'tcx> for PatternEquality {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if_chain! {
-            if !in_external_macro(cx.sess(), expr.span);
-            if let ExprKind::Let(let_expr) = expr.kind;
-            if unary_pattern(let_expr.pat);
+        if !in_external_macro(cx.sess(), expr.span)
+            && let ExprKind::Let(let_expr) = expr.kind
+            && unary_pattern(let_expr.pat) {
             let exp_ty = cx.typeck_results().expr_ty(let_expr.init);
             let pat_ty = cx.typeck_results().pat_ty(let_expr.pat);
-            if is_structural_partial_eq(cx, exp_ty, pat_ty);
-            then {
+            let mut applicability = Applicability::MachineApplicable;
 
-                let mut applicability = Applicability::MachineApplicable;
+            if is_structural_partial_eq(cx, exp_ty, pat_ty) {
                 let pat_str = match let_expr.pat.kind {
                     PatKind::Struct(..) => format!(
                         "({})",
@@ -96,6 +93,20 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality {
                     ),
                     applicability,
                 );
+            } else {
+                span_lint_and_sugg(
+                    cx,
+                    EQUATABLE_IF_LET,
+                    expr.span,
+                    "this pattern matching can be expressed using `matches!`",
+                    "try",
+                    format!(
+                        "matches!({}, {})",
+                        snippet_with_context(cx, let_expr.init.span, expr.span.ctxt(), "..", &mut applicability).0,
+                        snippet_with_context(cx, let_expr.pat.span, expr.span.ctxt(), "..", &mut applicability).0,
+                    ),
+                    applicability,
+                );
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index 7f1a4c4beb1..1d09adec12f 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -176,13 +176,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
         }
     }
 
-    fn fake_read(
-        &mut self,
-        _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>,
-        _: FakeReadCause,
-        _: HirId,
-    ) {
-    }
+    fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
 }
 
 impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs
index 453471c8cdd..fc2912f696e 100644
--- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs
+++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs
@@ -1,8 +1,11 @@
 use clippy_utils::diagnostics::span_lint_and_help;
-use rustc_ast::ast::{AssocItemKind, Extern, Fn, FnSig, Impl, Item, ItemKind, Trait, Ty, TyKind};
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use clippy_utils::{get_parent_as_impl, has_repr_attr, is_bool};
+use rustc_hir::intravisit::FnKind;
+use rustc_hir::{Body, FnDecl, HirId, Item, ItemKind, TraitFn, TraitItem, TraitItemKind, Ty};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::{sym, Span};
+use rustc_span::Span;
+use rustc_target::spec::abi::Abi;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -83,6 +86,12 @@ pub struct ExcessiveBools {
     max_fn_params_bools: u64,
 }
 
+#[derive(Eq, PartialEq, Debug, Copy, Clone)]
+enum Kind {
+    Struct,
+    Fn,
+}
+
 impl ExcessiveBools {
     #[must_use]
     pub fn new(max_struct_bools: u64, max_fn_params_bools: u64) -> Self {
@@ -92,21 +101,20 @@ impl ExcessiveBools {
         }
     }
 
-    fn check_fn_sig(&self, cx: &EarlyContext<'_>, fn_sig: &FnSig, span: Span) {
-        match fn_sig.header.ext {
-            Extern::Implicit(_) | Extern::Explicit(_, _) => return,
-            Extern::None => (),
+    fn too_many_bools<'tcx>(&self, tys: impl Iterator<Item = &'tcx Ty<'tcx>>, kind: Kind) -> bool {
+        if let Ok(bools) = tys.filter(|ty| is_bool(ty)).count().try_into() {
+            (if Kind::Fn == kind {
+                self.max_fn_params_bools
+            } else {
+                self.max_struct_bools
+            }) < bools
+        } else {
+            false
         }
+    }
 
-        let fn_sig_bools = fn_sig
-            .decl
-            .inputs
-            .iter()
-            .filter(|param| is_bool_ty(&param.ty))
-            .count()
-            .try_into()
-            .unwrap();
-        if self.max_fn_params_bools < fn_sig_bools {
+    fn check_fn_sig(&self, cx: &LateContext<'_>, fn_decl: &FnDecl<'_>, span: Span) {
+        if !span.from_expansion() && self.too_many_bools(fn_decl.inputs.iter(), Kind::Fn) {
             span_lint_and_help(
                 cx,
                 FN_PARAMS_EXCESSIVE_BOOLS,
@@ -121,56 +129,55 @@ impl ExcessiveBools {
 
 impl_lint_pass!(ExcessiveBools => [STRUCT_EXCESSIVE_BOOLS, FN_PARAMS_EXCESSIVE_BOOLS]);
 
-fn is_bool_ty(ty: &Ty) -> bool {
-    if let TyKind::Path(None, path) = &ty.kind {
-        if let [name] = path.segments.as_slice() {
-            return name.ident.name == sym::bool;
+impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+        if item.span.from_expansion() {
+            return;
+        }
+        if let ItemKind::Struct(variant_data, _) = &item.kind {
+            if has_repr_attr(cx, item.hir_id()) {
+                return;
+            }
+
+            if self.too_many_bools(variant_data.fields().iter().map(|field| field.ty), Kind::Struct) {
+                span_lint_and_help(
+                    cx,
+                    STRUCT_EXCESSIVE_BOOLS,
+                    item.span,
+                    &format!("more than {} bools in a struct", self.max_struct_bools),
+                    None,
+                    "consider using a state machine or refactoring bools into two-variant enums",
+                );
+            }
         }
     }
-    false
-}
 
-impl EarlyLintPass for ExcessiveBools {
-    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if item.span.from_expansion() {
-            return;
+    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx TraitItem<'tcx>) {
+        // functions with a body are already checked by `check_fn`
+        if let TraitItemKind::Fn(fn_sig, TraitFn::Required(_)) = &trait_item.kind
+            && fn_sig.header.abi == Abi::Rust
+            {
+            self.check_fn_sig(cx, fn_sig.decl, fn_sig.span);
         }
-        match &item.kind {
-            ItemKind::Struct(variant_data, _) => {
-                if item.attrs.iter().any(|attr| attr.has_name(sym::repr)) {
-                    return;
-                }
+    }
 
-                let struct_bools = variant_data
-                    .fields()
-                    .iter()
-                    .filter(|field| is_bool_ty(&field.ty))
-                    .count()
-                    .try_into()
-                    .unwrap();
-                if self.max_struct_bools < struct_bools {
-                    span_lint_and_help(
-                        cx,
-                        STRUCT_EXCESSIVE_BOOLS,
-                        item.span,
-                        &format!("more than {} bools in a struct", self.max_struct_bools),
-                        None,
-                        "consider using a state machine or refactoring bools into two-variant enums",
-                    );
-                }
-            },
-            ItemKind::Impl(box Impl {
-                of_trait: None, items, ..
-            })
-            | ItemKind::Trait(box Trait { items, .. }) => {
-                for item in items {
-                    if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
-                        self.check_fn_sig(cx, sig, item.span);
-                    }
-                }
-            },
-            ItemKind::Fn(box Fn { sig, .. }) => self.check_fn_sig(cx, sig, item.span),
-            _ => (),
+    fn check_fn(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        fn_kind: FnKind<'tcx>,
+        fn_decl: &'tcx FnDecl<'tcx>,
+        _: &'tcx Body<'tcx>,
+        span: Span,
+        hir_id: HirId,
+    ) {
+        if let Some(fn_header) = fn_kind.header()
+            && fn_header.abi == Abi::Rust
+            && get_parent_as_impl(cx.tcx, hir_id)
+                .map_or(true,
+                    |impl_item| impl_item.of_trait.is_none()
+                )
+            {
+            self.check_fn_sig(cx, fn_decl, span);
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
index 0a633f242a5..9a1058470e1 100644
--- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
+++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
@@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom {
     }
 }
 
-fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[hir::ImplItemRef]) {
+fn lint_impl_body(cx: &LateContext<'_>, impl_span: Span, impl_items: &[hir::ImplItemRef]) {
     use rustc_hir::intravisit::{self, Visitor};
     use rustc_hir::{Expr, ImplItemKind};
 
diff --git a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
new file mode 100644
index 00000000000..00f5ba56496
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
@@ -0,0 +1,77 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::ty::is_c_void;
+use clippy_utils::{match_def_path, path_def_id, paths};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{Expr, ExprKind, QPath};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::RawPtr;
+use rustc_middle::ty::TypeAndMut;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks if we're passing a `c_void` raw pointer to `{Box,Rc,Arc,Weak}::from_raw(_)`
+    ///
+    /// ### Why is this bad?
+    /// When dealing with `c_void` raw pointers in FFI, it is easy to run into the pitfall of calling `from_raw` with the `c_void` pointer.
+    /// The type signature of `Box::from_raw` is `fn from_raw(raw: *mut T) -> Box<T>`, so if you pass a `*mut c_void` you will get a `Box<c_void>` (and similarly for `Rc`, `Arc` and `Weak`).
+    /// For this to be safe, `c_void` would need to have the same memory layout as the original type, which is often not the case.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # use std::ffi::c_void;
+    /// let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void;
+    /// let _ = unsafe { Box::from_raw(ptr) };
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # use std::ffi::c_void;
+    /// # let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void;
+    /// let _ = unsafe { Box::from_raw(ptr as *mut usize) };
+    /// ```
+    ///
+    #[clippy::version = "1.66.0"]
+    pub FROM_RAW_WITH_VOID_PTR,
+    suspicious,
+    "creating a `Box` from a void raw pointer"
+}
+declare_lint_pass!(FromRawWithVoidPtr => [FROM_RAW_WITH_VOID_PTR]);
+
+impl LateLintPass<'_> for FromRawWithVoidPtr {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        if let ExprKind::Call(box_from_raw, [arg]) = expr.kind
+        && let ExprKind::Path(QPath::TypeRelative(ty, seg)) = box_from_raw.kind
+        && seg.ident.name == sym!(from_raw)
+        && let Some(type_str) = path_def_id(cx, ty).and_then(|id| def_id_matches_type(cx, id))
+        && let arg_kind = cx.typeck_results().expr_ty(arg).kind()
+        && let RawPtr(TypeAndMut { ty, .. }) = arg_kind
+        && is_c_void(cx, *ty) {
+            let msg = format!("creating a `{type_str}` from a void raw pointer");
+            span_lint_and_help(cx, FROM_RAW_WITH_VOID_PTR, expr.span, &msg, Some(arg.span), "cast this to a pointer of the appropriate type");
+        }
+    }
+}
+
+/// Checks whether a `DefId` matches `Box`, `Rc`, `Arc`, or one of the `Weak` types.
+/// Returns a static string slice with the name of the type, if one was found.
+fn def_id_matches_type(cx: &LateContext<'_>, def_id: DefId) -> Option<&'static str> {
+    // Box
+    if Some(def_id) == cx.tcx.lang_items().owned_box() {
+        return Some("Box");
+    }
+
+    if let Some(symbol) = cx.tcx.get_diagnostic_name(def_id) {
+        if symbol == sym::Arc {
+            return Some("Arc");
+        } else if symbol == sym::Rc {
+            return Some("Rc");
+        }
+    }
+
+    if match_def_path(cx, def_id, &paths::WEAK_RC) || match_def_path(cx, def_id, &paths::WEAK_ARC) {
+        Some("Weak")
+    } else {
+        None
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs
index 90911e0bf25..ae0e0833446 100644
--- a/src/tools/clippy/clippy_lints/src/functions/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs
@@ -254,7 +254,7 @@ declare_clippy_lint! {
     ///     Ok(())
     /// }
     /// ```
-    #[clippy::version = "1.64.0"]
+    #[clippy::version = "1.65.0"]
     pub RESULT_LARGE_ERR,
     perf,
     "function returning `Result` with large `Err` type"
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index bff69f91518..d22bede36b4 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -50,7 +50,9 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
         let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
         if let Some(attr) = attr {
             check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
-        } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.owner_id.def_id).is_none()
+        } else if is_public
+            && !is_proc_macro(cx.sess(), attrs)
+            && trait_ref_of_method(cx, item.owner_id.def_id).is_none()
         {
             check_must_use_candidate(
                 cx,
@@ -175,7 +177,7 @@ fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet)
         return false; // ignore `_` patterns
     }
     if cx.tcx.has_typeck_results(pat.hir_id.owner.to_def_id()) {
-        is_mutable_ty(cx, cx.tcx.typeck(pat.hir_id.owner.def_id).pat_ty(pat), pat.span, tys)
+        is_mutable_ty(cx, cx.tcx.typeck(pat.hir_id.owner.def_id).pat_ty(pat), tys)
     } else {
         false
     }
@@ -183,7 +185,7 @@ fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet)
 
 static KNOWN_WRAPPER_TYS: &[Symbol] = &[sym::Rc, sym::Arc];
 
-fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &mut DefIdSet) -> bool {
+fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet) -> bool {
     match *ty.kind() {
         // primitive types are never mutable
         ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false,
@@ -192,12 +194,12 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &m
                 || KNOWN_WRAPPER_TYS
                     .iter()
                     .any(|&sym| cx.tcx.is_diagnostic_item(sym, adt.did()))
-                    && substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys))
+                    && substs.types().any(|ty| is_mutable_ty(cx, ty, tys))
         },
-        ty::Tuple(substs) => substs.iter().any(|ty| is_mutable_ty(cx, ty, span, tys)),
-        ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, span, tys),
+        ty::Tuple(substs) => substs.iter().any(|ty| is_mutable_ty(cx, ty, tys)),
+        ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, tys),
         ty::RawPtr(ty::TypeAndMut { ty, mutbl }) | ty::Ref(_, ty, mutbl) => {
-            mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, span, tys)
+            mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, tys)
         },
         // calling something constitutes a side effect, so return true on all callables
         // also never calls need not be used, so return true for them, too
@@ -225,12 +227,7 @@ fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bo
                 let mut tys = DefIdSet::default();
                 for arg in args {
                     if cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
-                        && is_mutable_ty(
-                            cx,
-                            cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg),
-                            arg.span,
-                            &mut tys,
-                        )
+                        && is_mutable_ty(cx, cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg), &mut tys)
                         && is_mutated_static(arg)
                     {
                         return ControlFlow::Break(());
@@ -243,12 +240,7 @@ fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bo
                 let mut tys = DefIdSet::default();
                 for arg in std::iter::once(receiver).chain(args.iter()) {
                     if cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
-                        && is_mutable_ty(
-                            cx,
-                            cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg),
-                            arg.span,
-                            &mut tys,
-                        )
+                        && is_mutable_ty(cx, cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg), &mut tys)
                         && is_mutated_static(arg)
                     {
                         return ControlFlow::Break(());
diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs
index 5c63fb2acb1..f7e30b051a6 100644
--- a/src/tools/clippy/clippy_lints/src/functions/result.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/result.rs
@@ -2,12 +2,12 @@ use rustc_errors::Diagnostic;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Adt, Ty};
 use rustc_span::{sym, Span};
 
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
 use clippy_utils::trait_ref_of_method;
-use clippy_utils::ty::{approx_ty_size, is_type_diagnostic_item};
+use clippy_utils::ty::{approx_ty_size, is_type_diagnostic_item, AdtVariantInfo};
 
 use super::{RESULT_LARGE_ERR, RESULT_UNIT_ERR};
 
@@ -84,17 +84,57 @@ fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: S
 }
 
 fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty_span: Span, large_err_threshold: u64) {
-    let ty_size = approx_ty_size(cx, err_ty);
-    if ty_size >= large_err_threshold {
-        span_lint_and_then(
-            cx,
-            RESULT_LARGE_ERR,
-            hir_ty_span,
-            "the `Err`-variant returned from this function is very large",
-            |diag: &mut Diagnostic| {
-                diag.span_label(hir_ty_span, format!("the `Err`-variant is at least {ty_size} bytes"));
-                diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`"));
-            },
-        );
+    if_chain! {
+        if let Adt(adt, subst) = err_ty.kind();
+        if let Some(local_def_id) = err_ty.ty_adt_def().expect("already checked this is adt").did().as_local();
+        if let Some(hir::Node::Item(item)) = cx
+            .tcx
+            .hir()
+            .find_by_def_id(local_def_id);
+        if let hir::ItemKind::Enum(ref def, _) = item.kind;
+        then {
+            let variants_size = AdtVariantInfo::new(cx, *adt, subst);
+            if variants_size[0].size >= large_err_threshold {
+                span_lint_and_then(
+                    cx,
+                    RESULT_LARGE_ERR,
+                    hir_ty_span,
+                    "the `Err`-variant returned from this function is very large",
+                    |diag| {
+                        diag.span_label(
+                            def.variants[variants_size[0].ind].span,
+                            format!("the largest variant contains at least {} bytes", variants_size[0].size),
+                        );
+
+                        for variant in &variants_size[1..] {
+                            if variant.size >= large_err_threshold {
+                                let variant_def = &def.variants[variant.ind];
+                                diag.span_label(
+                                    variant_def.span,
+                                    format!("the variant `{}` contains at least {} bytes", variant_def.ident, variant.size),
+                                );
+                            }
+                        }
+
+                        diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`"));
+                    }
+                );
+            }
+        }
+        else {
+            let ty_size = approx_ty_size(cx, err_ty);
+            if ty_size >= large_err_threshold {
+                span_lint_and_then(
+                    cx,
+                    RESULT_LARGE_ERR,
+                    hir_ty_span,
+                    "the `Err`-variant returned from this function is very large",
+                    |diag: &mut Diagnostic| {
+                        diag.span_label(hir_ty_span, format!("the `Err`-variant is at least {ty_size} bytes"));
+                        diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`"));
+                    },
+                );
+            }
+        }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
index 94e06cf704b..64a4a3fa741 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
@@ -66,8 +66,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
         use rustc_span::BytePos;
 
-        fn suggestion<'tcx>(
-            cx: &LateContext<'tcx>,
+        fn suggestion(
+            cx: &LateContext<'_>,
             diag: &mut Diagnostic,
             generics_span: Span,
             generics_suggestion_span: Span,
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 c7b5badaae5..0d5099bde6d 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -207,8 +207,8 @@ impl SliceLintInformation {
     }
 }
 
-fn filter_lintable_slices<'a, 'tcx>(
-    cx: &'a LateContext<'tcx>,
+fn filter_lintable_slices<'tcx>(
+    cx: &LateContext<'tcx>,
     slice_lint_info: FxIndexMap<hir::HirId, SliceLintInformation>,
     max_suggested_slice: u64,
     scope: &'tcx hir::Expr<'tcx>,
diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
index af40a5a8187..4cd7dff4cfd 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -171,11 +171,7 @@ 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<'tcx>(
-    cx: &LateContext<'tcx>,
-    range: higher::Range<'_>,
-    array_size: u128,
-) -> (Option<u128>, Option<u128>) {
+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));
diff --git a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
new file mode 100644
index 00000000000..60754b224fc
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
@@ -0,0 +1,184 @@
+use clippy_utils::{
+    diagnostics::{self, span_lint_and_sugg},
+    meets_msrv, msrvs, source,
+    sugg::Sugg,
+    ty,
+};
+use rustc_errors::Applicability;
+use rustc_hir::{BinOpKind, Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{source_map::Spanned, sym};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Lints subtraction between `Instant::now()` and another `Instant`.
+    ///
+    /// ### Why is this bad?
+    /// It is easy to accidentally write `prev_instant - Instant::now()`, which will always be 0ns
+    /// as `Instant` subtraction saturates.
+    ///
+    /// `prev_instant.elapsed()` also more clearly signals intention.
+    ///
+    /// ### Example
+    /// ```rust
+    /// use std::time::Instant;
+    /// let prev_instant = Instant::now();
+    /// let duration = Instant::now() - prev_instant;
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// use std::time::Instant;
+    /// let prev_instant = Instant::now();
+    /// let duration = prev_instant.elapsed();
+    /// ```
+    #[clippy::version = "1.65.0"]
+    pub MANUAL_INSTANT_ELAPSED,
+    pedantic,
+    "subtraction between `Instant::now()` and previous `Instant`"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Lints subtraction between an [`Instant`] and a [`Duration`].
+    ///
+    /// ### Why is this bad?
+    /// Unchecked subtraction could cause underflow on certain platforms, leading to
+    /// unintentional panics.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # use std::time::{Instant, Duration};
+    /// let time_passed = Instant::now() - Duration::from_secs(5);
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust
+    /// # use std::time::{Instant, Duration};
+    /// let time_passed = Instant::now().checked_sub(Duration::from_secs(5));
+    /// ```
+    ///
+    /// [`Duration`]: std::time::Duration
+    /// [`Instant::now()`]: std::time::Instant::now;
+    #[clippy::version = "1.65.0"]
+    pub UNCHECKED_DURATION_SUBTRACTION,
+    suspicious,
+    "finds unchecked subtraction of a 'Duration' from an 'Instant'"
+}
+
+pub struct InstantSubtraction {
+    msrv: Option<RustcVersion>,
+}
+
+impl InstantSubtraction {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        Self { msrv }
+    }
+}
+
+impl_lint_pass!(InstantSubtraction => [MANUAL_INSTANT_ELAPSED, UNCHECKED_DURATION_SUBTRACTION]);
+
+impl LateLintPass<'_> for InstantSubtraction {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
+        if let ExprKind::Binary(
+            Spanned {
+                node: BinOpKind::Sub, ..
+            },
+            lhs,
+            rhs,
+        ) = expr.kind
+        {
+            if_chain! {
+                if is_instant_now_call(cx, lhs);
+
+                if is_an_instant(cx, rhs);
+                if let Some(sugg) = Sugg::hir_opt(cx, rhs);
+
+                then {
+                    print_manual_instant_elapsed_sugg(cx, expr, sugg)
+                } else {
+                    if_chain! {
+                        if !expr.span.from_expansion();
+                        if meets_msrv(self.msrv, msrvs::TRY_FROM);
+
+                        if is_an_instant(cx, lhs);
+                        if is_a_duration(cx, rhs);
+
+                        then {
+                            print_unchecked_duration_subtraction_sugg(cx, lhs, rhs, expr)
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    extract_msrv_attr!(LateContext);
+}
+
+fn is_instant_now_call(cx: &LateContext<'_>, expr_block: &'_ Expr<'_>) -> bool {
+    if let ExprKind::Call(fn_expr, []) = expr_block.kind
+        && let Some(fn_id) = clippy_utils::path_def_id(cx, fn_expr)
+        && clippy_utils::match_def_path(cx, fn_id, &clippy_utils::paths::INSTANT_NOW)
+    {
+        true
+    } else {
+        false
+    }
+}
+
+fn is_an_instant(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    let expr_ty = cx.typeck_results().expr_ty(expr);
+
+    match expr_ty.kind() {
+        rustc_middle::ty::Adt(def, _) => clippy_utils::match_def_path(cx, def.did(), &clippy_utils::paths::INSTANT),
+        _ => false,
+    }
+}
+
+fn is_a_duration(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    let expr_ty = cx.typeck_results().expr_ty(expr);
+    ty::is_type_diagnostic_item(cx, expr_ty, sym::Duration)
+}
+
+fn print_manual_instant_elapsed_sugg(cx: &LateContext<'_>, expr: &Expr<'_>, sugg: Sugg<'_>) {
+    span_lint_and_sugg(
+        cx,
+        MANUAL_INSTANT_ELAPSED,
+        expr.span,
+        "manual implementation of `Instant::elapsed`",
+        "try",
+        format!("{}.elapsed()", sugg.maybe_par()),
+        Applicability::MachineApplicable,
+    );
+}
+
+fn print_unchecked_duration_subtraction_sugg(
+    cx: &LateContext<'_>,
+    left_expr: &Expr<'_>,
+    right_expr: &Expr<'_>,
+    expr: &Expr<'_>,
+) {
+    let mut applicability = Applicability::MachineApplicable;
+
+    let left_expr =
+        source::snippet_with_applicability(cx, left_expr.span, "std::time::Instant::now()", &mut applicability);
+    let right_expr = source::snippet_with_applicability(
+        cx,
+        right_expr.span,
+        "std::time::Duration::from_secs(1)",
+        &mut applicability,
+    );
+
+    diagnostics::span_lint_and_sugg(
+        cx,
+        UNCHECKED_DURATION_SUBTRACTION,
+        expr.span,
+        "unchecked subtraction of a 'Duration' from an 'Instant'",
+        "try",
+        format!("{left_expr}.checked_sub({right_expr}).unwrap()"),
+        applicability,
+    );
+}
diff --git a/src/tools/clippy/clippy_lints/src/int_plus_one.rs b/src/tools/clippy/clippy_lints/src/int_plus_one.rs
index f793abdfda3..1b14e525d9a 100644
--- a/src/tools/clippy/clippy_lints/src/int_plus_one.rs
+++ b/src/tools/clippy/clippy_lints/src/int_plus_one.rs
@@ -63,58 +63,54 @@ impl IntPlusOne {
     fn check_binop(cx: &EarlyContext<'_>, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option<String> {
         match (binop, &lhs.kind, &rhs.kind) {
             // case where `x - 1 >= ...` or `-1 + x >= ...`
-            (BinOpKind::Ge, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) => {
+            (BinOpKind::Ge, ExprKind::Binary(lhskind, lhslhs, lhsrhs), _) => {
                 match (lhskind.node, &lhslhs.kind, &lhsrhs.kind) {
                     // `-1 + x`
-                    (BinOpKind::Add, &ExprKind::Lit(lit), _) if Self::check_lit(lit, -1) => {
+                    (BinOpKind::Add, ExprKind::Lit(lit), _) if Self::check_lit(*lit, -1) => {
                         Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs)
                     },
                     // `x - 1`
-                    (BinOpKind::Sub, _, &ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
+                    (BinOpKind::Sub, _, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => {
                         Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs)
                     },
                     _ => None,
                 }
             },
             // case where `... >= y + 1` or `... >= 1 + y`
-            (BinOpKind::Ge, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs))
-                if rhskind.node == BinOpKind::Add =>
-            {
+            (BinOpKind::Ge, _, ExprKind::Binary(rhskind, rhslhs, rhsrhs)) if rhskind.node == BinOpKind::Add => {
                 match (&rhslhs.kind, &rhsrhs.kind) {
                     // `y + 1` and `1 + y`
-                    (&ExprKind::Lit(lit), _) if Self::check_lit(lit, 1) => {
+                    (ExprKind::Lit(lit), _) if Self::check_lit(*lit, 1) => {
                         Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs)
                     },
-                    (_, &ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
+                    (_, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => {
                         Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs)
                     },
                     _ => None,
                 }
             },
             // case where `x + 1 <= ...` or `1 + x <= ...`
-            (BinOpKind::Le, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _)
-                if lhskind.node == BinOpKind::Add =>
-            {
+            (BinOpKind::Le, ExprKind::Binary(lhskind, lhslhs, lhsrhs), _) if lhskind.node == BinOpKind::Add => {
                 match (&lhslhs.kind, &lhsrhs.kind) {
                     // `1 + x` and `x + 1`
-                    (&ExprKind::Lit(lit), _) if Self::check_lit(lit, 1) => {
+                    (ExprKind::Lit(lit), _) if Self::check_lit(*lit, 1) => {
                         Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs)
                     },
-                    (_, &ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
+                    (_, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => {
                         Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs)
                     },
                     _ => None,
                 }
             },
             // case where `... >= y - 1` or `... >= -1 + y`
-            (BinOpKind::Le, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) => {
+            (BinOpKind::Le, _, ExprKind::Binary(rhskind, rhslhs, rhsrhs)) => {
                 match (rhskind.node, &rhslhs.kind, &rhsrhs.kind) {
                     // `-1 + y`
-                    (BinOpKind::Add, &ExprKind::Lit(lit), _) if Self::check_lit(lit, -1) => {
+                    (BinOpKind::Add, ExprKind::Lit(lit), _) if Self::check_lit(*lit, -1) => {
                         Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs)
                     },
                     // `y - 1`
-                    (BinOpKind::Sub, _, &ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
+                    (BinOpKind::Sub, _, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => {
                         Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs)
                     },
                     _ => None,
diff --git a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
index 0ef77e03de9..6ea637412d5 100644
--- a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
@@ -38,7 +38,7 @@ declare_clippy_lint! {
 
 declare_lint_pass!(InvalidUpcastComparisons => [INVALID_UPCAST_COMPARISONS]);
 
-fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<(FullInt, FullInt)> {
+fn numeric_cast_precast_bounds(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<(FullInt, FullInt)> {
     if let ExprKind::Cast(cast_exp, _) = expr.kind {
         let pre_cast_ty = cx.typeck_results().expr_ty(cast_exp);
         let cast_ty = cx.typeck_results().expr_ty(expr);
diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
index 06e95728549..b18456ee523 100644
--- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
+++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
@@ -1,12 +1,15 @@
 //! lint when there is a large size difference between variants on an enum
 
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{diagnostics::span_lint_and_then, ty::approx_ty_size, ty::is_copy};
+use clippy_utils::{
+    diagnostics::span_lint_and_then,
+    ty::{approx_ty_size, is_copy, AdtVariantInfo},
+};
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{Adt, AdtDef, GenericArg, List, Ty};
+use rustc_middle::ty::{Adt, Ty};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
 
@@ -72,49 +75,6 @@ impl LargeEnumVariant {
     }
 }
 
-struct FieldInfo {
-    ind: usize,
-    size: u64,
-}
-
-struct VariantInfo {
-    ind: usize,
-    size: u64,
-    fields_size: Vec<FieldInfo>,
-}
-
-fn variants_size<'tcx>(
-    cx: &LateContext<'tcx>,
-    adt: AdtDef<'tcx>,
-    subst: &'tcx List<GenericArg<'tcx>>,
-) -> Vec<VariantInfo> {
-    let mut variants_size = adt
-        .variants()
-        .iter()
-        .enumerate()
-        .map(|(i, variant)| {
-            let mut fields_size = variant
-                .fields
-                .iter()
-                .enumerate()
-                .map(|(i, f)| FieldInfo {
-                    ind: i,
-                    size: approx_ty_size(cx, f.ty(cx.tcx, subst)),
-                })
-                .collect::<Vec<_>>();
-            fields_size.sort_by(|a, b| (a.size.cmp(&b.size)));
-
-            VariantInfo {
-                ind: i,
-                size: fields_size.iter().map(|info| info.size).sum(),
-                fields_size,
-            }
-        })
-        .collect::<Vec<_>>();
-    variants_size.sort_by(|a, b| (b.size.cmp(&a.size)));
-    variants_size
-}
-
 impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]);
 
 impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
@@ -130,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
             if adt.variants().len() <= 1 {
                 return;
             }
-            let variants_size = variants_size(cx, *adt, subst);
+            let variants_size = AdtVariantInfo::new(cx, *adt, subst);
 
             let mut difference = variants_size[0].size - variants_size[1].size;
             if difference > self.maximum_size_difference_allowed {
@@ -173,16 +133,16 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
                                 .fields_size
                                 .iter()
                                 .rev()
-                                .map_while(|val| {
+                                .map_while(|&(ind, size)| {
                                     if difference > self.maximum_size_difference_allowed {
-                                        difference = difference.saturating_sub(val.size);
+                                        difference = difference.saturating_sub(size);
                                         Some((
-                                            fields[val.ind].ty.span,
+                                            fields[ind].ty.span,
                                             format!(
                                                 "Box<{}>",
                                                 snippet_with_applicability(
                                                     cx,
-                                                    fields[val.ind].ty.span,
+                                                    fields[ind].ty.span,
                                                     "..",
                                                     &mut applicability
                                                 )
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index b0cba40c27a..4c133c06a15 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -366,8 +366,7 @@ fn check_for_is_empty<'tcx>(
 }
 
 fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) {
-    if let (&ExprKind::MethodCall(method_path, receiver, args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind)
-    {
+    if let (&ExprKind::MethodCall(method_path, receiver, args, _), ExprKind::Lit(lit)) = (&method.kind, &lit.kind) {
         // check if we are in an is_empty() method
         if let Some(name) = get_item_name(cx, method) {
             if name.as_str() == "is_empty" {
diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs
index b7798b1c1d7..61f87b91400 100644
--- a/src/tools/clippy/clippy_lints/src/let_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs
@@ -1,13 +1,11 @@
 use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::{is_must_use_ty, is_type_diagnostic_item, match_type};
+use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type};
 use clippy_utils::{is_must_use_func_call, paths};
-use if_chain::if_chain;
 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_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::{sym, Symbol};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -30,13 +28,14 @@ declare_clippy_lint! {
     #[clippy::version = "1.42.0"]
     pub LET_UNDERSCORE_MUST_USE,
     restriction,
-    "non-binding let on a `#[must_use]` expression"
+    "non-binding `let` on a `#[must_use]` expression"
 }
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for `let _ = sync_lock`.
-    /// This supports `mutex` and `rwlock` in `std::sync` and `parking_lot`.
+    /// Checks for `let _ = sync_lock`. This supports `mutex` and `rwlock` in
+    /// `parking_lot`. For `std` locks see the `rustc` lint
+    /// [`let_underscore_lock`](https://doc.rust-lang.org/nightly/rustc/lints/listing/deny-by-default.html#let-underscore-lock)
     ///
     /// ### Why is this bad?
     /// This statement immediately drops the lock instead of
@@ -57,50 +56,41 @@ declare_clippy_lint! {
     #[clippy::version = "1.43.0"]
     pub LET_UNDERSCORE_LOCK,
     correctness,
-    "non-binding let on a synchronization lock"
+    "non-binding `let` on a synchronization lock"
 }
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for `let _ = <expr>`
-    /// where expr has a type that implements `Drop`
+    /// Checks for `let _ = <expr>` where the resulting type of expr implements `Future`
     ///
     /// ### Why is this bad?
-    /// This statement immediately drops the initializer
-    /// expression instead of extending its lifetime to the end of the scope, which
-    /// is often not intended. To extend the expression's lifetime to the end of the
-    /// scope, use an underscore-prefixed name instead (i.e. _var). If you want to
-    /// explicitly drop the expression, `std::mem::drop` conveys your intention
-    /// better and is less error-prone.
+    /// Futures must be polled for work to be done. The original intention was most likely to await the future
+    /// and ignore the resulting value.
     ///
     /// ### Example
     /// ```rust
-    /// # struct DroppableItem;
-    /// {
-    ///     let _ = DroppableItem;
-    ///     //                   ^ dropped here
-    ///     /* more code */
+    /// async fn foo() -> Result<(), ()> {
+    ///     Ok(())
     /// }
+    /// let _ = foo();
     /// ```
     ///
     /// Use instead:
     /// ```rust
-    /// # struct DroppableItem;
-    /// {
-    ///     let _droppable = DroppableItem;
-    ///     /* more code */
-    ///     // dropped at end of scope
+    /// # async fn context() {
+    /// async fn foo() -> Result<(), ()> {
+    ///     Ok(())
     /// }
+    /// let _ = foo().await;
+    /// # }
     /// ```
-    #[clippy::version = "1.50.0"]
-    pub LET_UNDERSCORE_DROP,
-    pedantic,
-    "non-binding let on a type that implements `Drop`"
+    #[clippy::version = "1.66"]
+    pub LET_UNDERSCORE_FUTURE,
+    suspicious,
+    "non-binding `let` on a future"
 }
 
-declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_DROP]);
-
-const SYNC_GUARD_SYMS: [Symbol; 3] = [sym::MutexGuard, sym::RwLockReadGuard, sym::RwLockWriteGuard];
+declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_FUTURE]);
 
 const SYNC_GUARD_PATHS: [&[&str]; 3] = [
     &paths::PARKING_LOT_MUTEX_GUARD,
@@ -110,64 +100,53 @@ const SYNC_GUARD_PATHS: [&[&str]; 3] = [
 
 impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
     fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
-        if in_external_macro(cx.tcx.sess, local.span) {
-            return;
-        }
-
-        if_chain! {
-            if let PatKind::Wild = local.pat.kind;
-            if let Some(init) = local.init;
-            then {
-                let init_ty = cx.typeck_results().expr_ty(init);
-                let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() {
-                    GenericArgKind::Type(inner_ty) => {
-                        SYNC_GUARD_SYMS
-                            .iter()
-                            .any(|&sym| is_type_diagnostic_item(cx, inner_ty, sym))
-                            || SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, inner_ty, path))
-                    },
-
-                    GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
-                });
-                if contains_sync_guard {
-                    span_lint_and_help(
-                        cx,
-                        LET_UNDERSCORE_LOCK,
-                        local.span,
-                        "non-binding let on a synchronization lock",
-                        None,
-                        "consider using an underscore-prefixed named \
-                            binding or dropping explicitly with `std::mem::drop`",
-                    );
-                } else if init_ty.needs_drop(cx.tcx, cx.param_env) {
-                    span_lint_and_help(
-                        cx,
-                        LET_UNDERSCORE_DROP,
-                        local.span,
-                        "non-binding `let` on a type that implements `Drop`",
-                        None,
-                        "consider using an underscore-prefixed named \
+        if !in_external_macro(cx.tcx.sess, local.span)
+            && let PatKind::Wild = local.pat.kind
+            && let Some(init) = local.init
+        {
+            let init_ty = cx.typeck_results().expr_ty(init);
+            let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() {
+                GenericArgKind::Type(inner_ty) => SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, inner_ty, path)),
+                GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
+            });
+            if contains_sync_guard {
+                span_lint_and_help(
+                    cx,
+                    LET_UNDERSCORE_LOCK,
+                    local.span,
+                    "non-binding `let` on a synchronization lock",
+                    None,
+                    "consider using an underscore-prefixed named \
                             binding or dropping explicitly with `std::mem::drop`",
-                    );
-                } else if is_must_use_ty(cx, cx.typeck_results().expr_ty(init)) {
-                    span_lint_and_help(
-                        cx,
-                        LET_UNDERSCORE_MUST_USE,
-                        local.span,
-                        "non-binding let on an expression with `#[must_use]` type",
-                        None,
-                        "consider explicitly using expression value",
-                    );
-                } else if is_must_use_func_call(cx, init) {
-                    span_lint_and_help(
-                        cx,
-                        LET_UNDERSCORE_MUST_USE,
-                        local.span,
-                        "non-binding let on a result of a `#[must_use]` function",
-                        None,
-                        "consider explicitly using function result",
-                    );
-                }
+                );
+            } else if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait()
+                && implements_trait(cx, cx.typeck_results().expr_ty(init), future_trait_def_id, &[]) {
+                span_lint_and_help(
+                    cx,
+                    LET_UNDERSCORE_FUTURE,
+                    local.span,
+                    "non-binding `let` on a future",
+                    None,
+                    "consider awaiting the future or dropping explicitly with `std::mem::drop`"
+                );
+            } else if is_must_use_ty(cx, cx.typeck_results().expr_ty(init)) {
+                span_lint_and_help(
+                    cx,
+                    LET_UNDERSCORE_MUST_USE,
+                    local.span,
+                    "non-binding `let` on an expression with `#[must_use]` type",
+                    None,
+                    "consider explicitly using expression value",
+                );
+            } else if is_must_use_func_call(cx, init) {
+                span_lint_and_help(
+                    cx,
+                    LET_UNDERSCORE_MUST_USE,
+                    local.span,
+                    "non-binding `let` on a result of a `#[must_use]` function",
+                    None,
+                    "consider explicitly using function result",
+                );
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_all.rs b/src/tools/clippy/clippy_lints/src/lib.register_all.rs
deleted file mode 100644
index c455e1561b7..00000000000
--- a/src/tools/clippy/clippy_lints/src/lib.register_all.rs
+++ /dev/null
@@ -1,368 +0,0 @@
-// This file was generated by `cargo dev update_lints`.
-// Use that command to update this file and do not edit by hand.
-// Manual edits will be overwritten.
-
-store.register_group(true, "clippy::all", Some("clippy_all"), vec![
-    LintId::of(almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE),
-    LintId::of(approx_const::APPROX_CONSTANT),
-    LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
-    LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC),
-    LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
-    LintId::of(attrs::DEPRECATED_CFG_ATTR),
-    LintId::of(attrs::DEPRECATED_SEMVER),
-    LintId::of(attrs::MISMATCHED_TARGET_OS),
-    LintId::of(attrs::USELESS_ATTRIBUTE),
-    LintId::of(await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE),
-    LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK),
-    LintId::of(await_holding_invalid::AWAIT_HOLDING_REFCELL_REF),
-    LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS),
-    LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON),
-    LintId::of(bool_to_int_with_if::BOOL_TO_INT_WITH_IF),
-    LintId::of(booleans::NONMINIMAL_BOOL),
-    LintId::of(booleans::OVERLY_COMPLEX_BOOL_EXPR),
-    LintId::of(borrow_deref_ref::BORROW_DEREF_REF),
-    LintId::of(box_default::BOX_DEFAULT),
-    LintId::of(casts::CAST_ABS_TO_UNSIGNED),
-    LintId::of(casts::CAST_ENUM_CONSTRUCTOR),
-    LintId::of(casts::CAST_ENUM_TRUNCATION),
-    LintId::of(casts::CAST_NAN_TO_INT),
-    LintId::of(casts::CAST_REF_TO_MUT),
-    LintId::of(casts::CAST_SLICE_DIFFERENT_SIZES),
-    LintId::of(casts::CAST_SLICE_FROM_RAW_PARTS),
-    LintId::of(casts::CHAR_LIT_AS_U8),
-    LintId::of(casts::FN_TO_NUMERIC_CAST),
-    LintId::of(casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION),
-    LintId::of(casts::UNNECESSARY_CAST),
-    LintId::of(collapsible_if::COLLAPSIBLE_ELSE_IF),
-    LintId::of(collapsible_if::COLLAPSIBLE_IF),
-    LintId::of(comparison_chain::COMPARISON_CHAIN),
-    LintId::of(copies::IFS_SAME_COND),
-    LintId::of(copies::IF_SAME_THEN_ELSE),
-    LintId::of(crate_in_macro_def::CRATE_IN_MACRO_DEF),
-    LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT),
-    LintId::of(default_instead_of_iter_empty::DEFAULT_INSTEAD_OF_ITER_EMPTY),
-    LintId::of(dereference::EXPLICIT_AUTO_DEREF),
-    LintId::of(dereference::NEEDLESS_BORROW),
-    LintId::of(derivable_impls::DERIVABLE_IMPLS),
-    LintId::of(derive::DERIVE_HASH_XOR_EQ),
-    LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD),
-    LintId::of(disallowed_macros::DISALLOWED_MACROS),
-    LintId::of(disallowed_methods::DISALLOWED_METHODS),
-    LintId::of(disallowed_names::DISALLOWED_NAMES),
-    LintId::of(disallowed_types::DISALLOWED_TYPES),
-    LintId::of(doc::MISSING_SAFETY_DOC),
-    LintId::of(doc::NEEDLESS_DOCTEST_MAIN),
-    LintId::of(double_parens::DOUBLE_PARENS),
-    LintId::of(drop_forget_ref::DROP_COPY),
-    LintId::of(drop_forget_ref::DROP_NON_DROP),
-    LintId::of(drop_forget_ref::DROP_REF),
-    LintId::of(drop_forget_ref::FORGET_COPY),
-    LintId::of(drop_forget_ref::FORGET_NON_DROP),
-    LintId::of(drop_forget_ref::FORGET_REF),
-    LintId::of(drop_forget_ref::UNDROPPED_MANUALLY_DROPS),
-    LintId::of(duplicate_mod::DUPLICATE_MOD),
-    LintId::of(entry::MAP_ENTRY),
-    LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT),
-    LintId::of(enum_variants::ENUM_VARIANT_NAMES),
-    LintId::of(enum_variants::MODULE_INCEPTION),
-    LintId::of(escape::BOXED_LOCAL),
-    LintId::of(eta_reduction::REDUNDANT_CLOSURE),
-    LintId::of(explicit_write::EXPLICIT_WRITE),
-    LintId::of(float_literal::EXCESSIVE_PRECISION),
-    LintId::of(format::USELESS_FORMAT),
-    LintId::of(format_args::FORMAT_IN_FORMAT_ARGS),
-    LintId::of(format_args::TO_STRING_IN_FORMAT_ARGS),
-    LintId::of(format_args::UNUSED_FORMAT_SPECS),
-    LintId::of(format_impl::PRINT_IN_FORMAT_IMPL),
-    LintId::of(format_impl::RECURSIVE_FORMAT_IMPL),
-    LintId::of(formatting::POSSIBLE_MISSING_COMMA),
-    LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
-    LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING),
-    LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
-    LintId::of(from_over_into::FROM_OVER_INTO),
-    LintId::of(from_str_radix_10::FROM_STR_RADIX_10),
-    LintId::of(functions::DOUBLE_MUST_USE),
-    LintId::of(functions::MUST_USE_UNIT),
-    LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF),
-    LintId::of(functions::RESULT_LARGE_ERR),
-    LintId::of(functions::RESULT_UNIT_ERR),
-    LintId::of(functions::TOO_MANY_ARGUMENTS),
-    LintId::of(if_let_mutex::IF_LET_MUTEX),
-    LintId::of(implicit_saturating_add::IMPLICIT_SATURATING_ADD),
-    LintId::of(implicit_saturating_sub::IMPLICIT_SATURATING_SUB),
-    LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING),
-    LintId::of(infinite_iter::INFINITE_ITER),
-    LintId::of(inherent_to_string::INHERENT_TO_STRING),
-    LintId::of(inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
-    LintId::of(init_numbered_fields::INIT_NUMBERED_FIELDS),
-    LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
-    LintId::of(int_plus_one::INT_PLUS_ONE),
-    LintId::of(invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED),
-    LintId::of(large_const_arrays::LARGE_CONST_ARRAYS),
-    LintId::of(large_enum_variant::LARGE_ENUM_VARIANT),
-    LintId::of(len_zero::COMPARISON_TO_EMPTY),
-    LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY),
-    LintId::of(len_zero::LEN_ZERO),
-    LintId::of(let_underscore::LET_UNDERSCORE_LOCK),
-    LintId::of(lifetimes::EXTRA_UNUSED_LIFETIMES),
-    LintId::of(lifetimes::NEEDLESS_LIFETIMES),
-    LintId::of(literal_representation::INCONSISTENT_DIGIT_GROUPING),
-    LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES),
-    LintId::of(literal_representation::UNUSUAL_BYTE_GROUPINGS),
-    LintId::of(loops::EMPTY_LOOP),
-    LintId::of(loops::EXPLICIT_COUNTER_LOOP),
-    LintId::of(loops::FOR_KV_MAP),
-    LintId::of(loops::ITER_NEXT_LOOP),
-    LintId::of(loops::MANUAL_FIND),
-    LintId::of(loops::MANUAL_FLATTEN),
-    LintId::of(loops::MANUAL_MEMCPY),
-    LintId::of(loops::MISSING_SPIN_LOOP),
-    LintId::of(loops::MUT_RANGE_BOUND),
-    LintId::of(loops::NEEDLESS_COLLECT),
-    LintId::of(loops::NEEDLESS_RANGE_LOOP),
-    LintId::of(loops::NEVER_LOOP),
-    LintId::of(loops::SAME_ITEM_PUSH),
-    LintId::of(loops::SINGLE_ELEMENT_LOOP),
-    LintId::of(loops::WHILE_IMMUTABLE_CONDITION),
-    LintId::of(loops::WHILE_LET_LOOP),
-    LintId::of(loops::WHILE_LET_ON_ITERATOR),
-    LintId::of(main_recursion::MAIN_RECURSION),
-    LintId::of(manual_async_fn::MANUAL_ASYNC_FN),
-    LintId::of(manual_bits::MANUAL_BITS),
-    LintId::of(manual_clamp::MANUAL_CLAMP),
-    LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE),
-    LintId::of(manual_rem_euclid::MANUAL_REM_EUCLID),
-    LintId::of(manual_retain::MANUAL_RETAIN),
-    LintId::of(manual_strip::MANUAL_STRIP),
-    LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN),
-    LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN),
-    LintId::of(match_result_ok::MATCH_RESULT_OK),
-    LintId::of(matches::COLLAPSIBLE_MATCH),
-    LintId::of(matches::INFALLIBLE_DESTRUCTURING_MATCH),
-    LintId::of(matches::MANUAL_FILTER),
-    LintId::of(matches::MANUAL_MAP),
-    LintId::of(matches::MANUAL_UNWRAP_OR),
-    LintId::of(matches::MATCH_AS_REF),
-    LintId::of(matches::MATCH_LIKE_MATCHES_MACRO),
-    LintId::of(matches::MATCH_OVERLAPPING_ARM),
-    LintId::of(matches::MATCH_REF_PATS),
-    LintId::of(matches::MATCH_SINGLE_BINDING),
-    LintId::of(matches::MATCH_STR_CASE_MISMATCH),
-    LintId::of(matches::NEEDLESS_MATCH),
-    LintId::of(matches::REDUNDANT_PATTERN_MATCHING),
-    LintId::of(matches::SINGLE_MATCH),
-    LintId::of(matches::WILDCARD_IN_OR_PATTERNS),
-    LintId::of(mem_replace::MEM_REPLACE_OPTION_WITH_NONE),
-    LintId::of(mem_replace::MEM_REPLACE_WITH_DEFAULT),
-    LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT),
-    LintId::of(methods::BIND_INSTEAD_OF_MAP),
-    LintId::of(methods::BYTES_COUNT_TO_LEN),
-    LintId::of(methods::BYTES_NTH),
-    LintId::of(methods::CHARS_LAST_CMP),
-    LintId::of(methods::CHARS_NEXT_CMP),
-    LintId::of(methods::CLONE_DOUBLE_REF),
-    LintId::of(methods::CLONE_ON_COPY),
-    LintId::of(methods::COLLAPSIBLE_STR_REPLACE),
-    LintId::of(methods::ERR_EXPECT),
-    LintId::of(methods::EXPECT_FUN_CALL),
-    LintId::of(methods::EXTEND_WITH_DRAIN),
-    LintId::of(methods::FILTER_MAP_IDENTITY),
-    LintId::of(methods::FILTER_NEXT),
-    LintId::of(methods::FLAT_MAP_IDENTITY),
-    LintId::of(methods::GET_FIRST),
-    LintId::of(methods::GET_LAST_WITH_LEN),
-    LintId::of(methods::INSPECT_FOR_EACH),
-    LintId::of(methods::INTO_ITER_ON_REF),
-    LintId::of(methods::IS_DIGIT_ASCII_RADIX),
-    LintId::of(methods::ITERATOR_STEP_BY_ZERO),
-    LintId::of(methods::ITER_CLONED_COLLECT),
-    LintId::of(methods::ITER_COUNT),
-    LintId::of(methods::ITER_KV_MAP),
-    LintId::of(methods::ITER_NEXT_SLICE),
-    LintId::of(methods::ITER_NTH),
-    LintId::of(methods::ITER_NTH_ZERO),
-    LintId::of(methods::ITER_OVEREAGER_CLONED),
-    LintId::of(methods::ITER_SKIP_NEXT),
-    LintId::of(methods::MANUAL_FILTER_MAP),
-    LintId::of(methods::MANUAL_FIND_MAP),
-    LintId::of(methods::MANUAL_SATURATING_ARITHMETIC),
-    LintId::of(methods::MANUAL_SPLIT_ONCE),
-    LintId::of(methods::MANUAL_STR_REPEAT),
-    LintId::of(methods::MAP_CLONE),
-    LintId::of(methods::MAP_COLLECT_RESULT_UNIT),
-    LintId::of(methods::MAP_FLATTEN),
-    LintId::of(methods::MAP_IDENTITY),
-    LintId::of(methods::MUT_MUTEX_LOCK),
-    LintId::of(methods::NEEDLESS_OPTION_AS_DEREF),
-    LintId::of(methods::NEEDLESS_OPTION_TAKE),
-    LintId::of(methods::NEEDLESS_SPLITN),
-    LintId::of(methods::NEW_RET_NO_SELF),
-    LintId::of(methods::NONSENSICAL_OPEN_OPTIONS),
-    LintId::of(methods::NO_EFFECT_REPLACE),
-    LintId::of(methods::OBFUSCATED_IF_ELSE),
-    LintId::of(methods::OK_EXPECT),
-    LintId::of(methods::OPTION_AS_REF_DEREF),
-    LintId::of(methods::OPTION_FILTER_MAP),
-    LintId::of(methods::OPTION_MAP_OR_NONE),
-    LintId::of(methods::OR_FUN_CALL),
-    LintId::of(methods::OR_THEN_UNWRAP),
-    LintId::of(methods::RANGE_ZIP_WITH_LEN),
-    LintId::of(methods::REPEAT_ONCE),
-    LintId::of(methods::RESULT_MAP_OR_INTO_OPTION),
-    LintId::of(methods::SEARCH_IS_SOME),
-    LintId::of(methods::SHOULD_IMPLEMENT_TRAIT),
-    LintId::of(methods::SINGLE_CHAR_ADD_STR),
-    LintId::of(methods::SINGLE_CHAR_PATTERN),
-    LintId::of(methods::SKIP_WHILE_NEXT),
-    LintId::of(methods::STRING_EXTEND_CHARS),
-    LintId::of(methods::SUSPICIOUS_MAP),
-    LintId::of(methods::SUSPICIOUS_SPLITN),
-    LintId::of(methods::SUSPICIOUS_TO_OWNED),
-    LintId::of(methods::UNINIT_ASSUMED_INIT),
-    LintId::of(methods::UNIT_HASH),
-    LintId::of(methods::UNNECESSARY_FILTER_MAP),
-    LintId::of(methods::UNNECESSARY_FIND_MAP),
-    LintId::of(methods::UNNECESSARY_FOLD),
-    LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS),
-    LintId::of(methods::UNNECESSARY_SORT_BY),
-    LintId::of(methods::UNNECESSARY_TO_OWNED),
-    LintId::of(methods::UNWRAP_OR_ELSE_DEFAULT),
-    LintId::of(methods::USELESS_ASREF),
-    LintId::of(methods::VEC_RESIZE_TO_ZERO),
-    LintId::of(methods::WRONG_SELF_CONVENTION),
-    LintId::of(methods::ZST_OFFSET),
-    LintId::of(minmax::MIN_MAX),
-    LintId::of(misc::SHORT_CIRCUIT_STATEMENT),
-    LintId::of(misc::TOPLEVEL_REF_ARG),
-    LintId::of(misc::ZERO_PTR),
-    LintId::of(misc_early::BUILTIN_TYPE_SHADOW),
-    LintId::of(misc_early::DOUBLE_NEG),
-    LintId::of(misc_early::DUPLICATE_UNDERSCORE_ARGUMENT),
-    LintId::of(misc_early::MIXED_CASE_HEX_LITERALS),
-    LintId::of(misc_early::REDUNDANT_PATTERN),
-    LintId::of(misc_early::UNNEEDED_WILDCARD_PATTERN),
-    LintId::of(misc_early::ZERO_PREFIXED_LITERAL),
-    LintId::of(mixed_read_write_in_expression::DIVERGING_SUB_EXPRESSION),
-    LintId::of(multi_assignments::MULTI_ASSIGNMENTS),
-    LintId::of(mut_key::MUTABLE_KEY_TYPE),
-    LintId::of(mut_reference::UNNECESSARY_MUT_PASSED),
-    LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE),
-    LintId::of(needless_bool::BOOL_COMPARISON),
-    LintId::of(needless_bool::NEEDLESS_BOOL),
-    LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
-    LintId::of(needless_late_init::NEEDLESS_LATE_INIT),
-    LintId::of(needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS),
-    LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK),
-    LintId::of(needless_update::NEEDLESS_UPDATE),
-    LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD),
-    LintId::of(neg_multiply::NEG_MULTIPLY),
-    LintId::of(new_without_default::NEW_WITHOUT_DEFAULT),
-    LintId::of(no_effect::NO_EFFECT),
-    LintId::of(no_effect::UNNECESSARY_OPERATION),
-    LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
-    LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
-    LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
-    LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS),
-    LintId::of(octal_escapes::OCTAL_ESCAPES),
-    LintId::of(only_used_in_recursion::ONLY_USED_IN_RECURSION),
-    LintId::of(operators::ABSURD_EXTREME_COMPARISONS),
-    LintId::of(operators::ASSIGN_OP_PATTERN),
-    LintId::of(operators::BAD_BIT_MASK),
-    LintId::of(operators::CMP_NAN),
-    LintId::of(operators::CMP_OWNED),
-    LintId::of(operators::DOUBLE_COMPARISONS),
-    LintId::of(operators::DURATION_SUBSEC),
-    LintId::of(operators::EQ_OP),
-    LintId::of(operators::ERASING_OP),
-    LintId::of(operators::FLOAT_EQUALITY_WITHOUT_ABS),
-    LintId::of(operators::IDENTITY_OP),
-    LintId::of(operators::INEFFECTIVE_BIT_MASK),
-    LintId::of(operators::MISREFACTORED_ASSIGN_OP),
-    LintId::of(operators::MODULO_ONE),
-    LintId::of(operators::OP_REF),
-    LintId::of(operators::PTR_EQ),
-    LintId::of(operators::SELF_ASSIGNMENT),
-    LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
-    LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
-    LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
-    LintId::of(partialeq_to_none::PARTIALEQ_TO_NONE),
-    LintId::of(precedence::PRECEDENCE),
-    LintId::of(ptr::CMP_NULL),
-    LintId::of(ptr::INVALID_NULL_PTR_USAGE),
-    LintId::of(ptr::MUT_FROM_REF),
-    LintId::of(ptr::PTR_ARG),
-    LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
-    LintId::of(question_mark::QUESTION_MARK),
-    LintId::of(ranges::MANUAL_RANGE_CONTAINS),
-    LintId::of(ranges::REVERSED_EMPTY_RANGES),
-    LintId::of(rc_clone_in_vec_init::RC_CLONE_IN_VEC_INIT),
-    LintId::of(read_zero_byte_vec::READ_ZERO_BYTE_VEC),
-    LintId::of(redundant_clone::REDUNDANT_CLONE),
-    LintId::of(redundant_closure_call::REDUNDANT_CLOSURE_CALL),
-    LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES),
-    LintId::of(redundant_slicing::REDUNDANT_SLICING),
-    LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
-    LintId::of(reference::DEREF_ADDROF),
-    LintId::of(regex::INVALID_REGEX),
-    LintId::of(returns::LET_AND_RETURN),
-    LintId::of(returns::NEEDLESS_RETURN),
-    LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS),
-    LintId::of(serde_api::SERDE_API_MISUSE),
-    LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
-    LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
-    LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
-    LintId::of(strings::STRING_FROM_UTF8_AS_BYTES),
-    LintId::of(strings::TRIM_SPLIT_WHITESPACE),
-    LintId::of(strlen_on_c_strings::STRLEN_ON_C_STRINGS),
-    LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
-    LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
-    LintId::of(swap::ALMOST_SWAPPED),
-    LintId::of(swap::MANUAL_SWAP),
-    LintId::of(swap_ptr_to_ref::SWAP_PTR_TO_REF),
-    LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
-    LintId::of(temporary_assignment::TEMPORARY_ASSIGNMENT),
-    LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME),
-    LintId::of(transmute::CROSSPOINTER_TRANSMUTE),
-    LintId::of(transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS),
-    LintId::of(transmute::TRANSMUTE_BYTES_TO_STR),
-    LintId::of(transmute::TRANSMUTE_FLOAT_TO_INT),
-    LintId::of(transmute::TRANSMUTE_INT_TO_BOOL),
-    LintId::of(transmute::TRANSMUTE_INT_TO_CHAR),
-    LintId::of(transmute::TRANSMUTE_INT_TO_FLOAT),
-    LintId::of(transmute::TRANSMUTE_NUM_TO_BYTES),
-    LintId::of(transmute::TRANSMUTE_PTR_TO_REF),
-    LintId::of(transmute::TRANSMUTING_NULL),
-    LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE),
-    LintId::of(transmute::USELESS_TRANSMUTE),
-    LintId::of(transmute::WRONG_TRANSMUTE),
-    LintId::of(types::BORROWED_BOX),
-    LintId::of(types::BOX_COLLECTION),
-    LintId::of(types::REDUNDANT_ALLOCATION),
-    LintId::of(types::TYPE_COMPLEXITY),
-    LintId::of(types::VEC_BOX),
-    LintId::of(unicode::INVISIBLE_CHARACTERS),
-    LintId::of(uninit_vec::UNINIT_VEC),
-    LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
-    LintId::of(unit_types::LET_UNIT_VALUE),
-    LintId::of(unit_types::UNIT_ARG),
-    LintId::of(unit_types::UNIT_CMP),
-    LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS),
-    LintId::of(unnamed_address::VTABLE_ADDRESS_COMPARISONS),
-    LintId::of(unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS),
-    LintId::of(unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
-    LintId::of(unused_io_amount::UNUSED_IO_AMOUNT),
-    LintId::of(unused_unit::UNUSED_UNIT),
-    LintId::of(unwrap::PANICKING_UNWRAP),
-    LintId::of(unwrap::UNNECESSARY_UNWRAP),
-    LintId::of(upper_case_acronyms::UPPER_CASE_ACRONYMS),
-    LintId::of(useless_conversion::USELESS_CONVERSION),
-    LintId::of(vec::USELESS_VEC),
-    LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH),
-    LintId::of(write::PRINTLN_EMPTY_STRING),
-    LintId::of(write::PRINT_LITERAL),
-    LintId::of(write::PRINT_WITH_NEWLINE),
-    LintId::of(write::WRITELN_EMPTY_STRING),
-    LintId::of(write::WRITE_LITERAL),
-    LintId::of(write::WRITE_WITH_NEWLINE),
-    LintId::of(zero_div_zero::ZERO_DIVIDED_BY_ZERO),
-])
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_cargo.rs b/src/tools/clippy/clippy_lints/src/lib.register_cargo.rs
deleted file mode 100644
index c890523fe5a..00000000000
--- a/src/tools/clippy/clippy_lints/src/lib.register_cargo.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-// This file was generated by `cargo dev update_lints`.
-// Use that command to update this file and do not edit by hand.
-// Manual edits will be overwritten.
-
-store.register_group(true, "clippy::cargo", Some("clippy_cargo"), vec![
-    LintId::of(cargo::CARGO_COMMON_METADATA),
-    LintId::of(cargo::MULTIPLE_CRATE_VERSIONS),
-    LintId::of(cargo::NEGATIVE_FEATURE_NAMES),
-    LintId::of(cargo::REDUNDANT_FEATURE_NAMES),
-    LintId::of(cargo::WILDCARD_DEPENDENCIES),
-])
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs b/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs
deleted file mode 100644
index 8be9dc4baf1..00000000000
--- a/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs
+++ /dev/null
@@ -1,111 +0,0 @@
-// This file was generated by `cargo dev update_lints`.
-// Use that command to update this file and do not edit by hand.
-// Manual edits will be overwritten.
-
-store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec![
-    LintId::of(attrs::DEPRECATED_CFG_ATTR),
-    LintId::of(booleans::NONMINIMAL_BOOL),
-    LintId::of(borrow_deref_ref::BORROW_DEREF_REF),
-    LintId::of(casts::CHAR_LIT_AS_U8),
-    LintId::of(casts::UNNECESSARY_CAST),
-    LintId::of(dereference::EXPLICIT_AUTO_DEREF),
-    LintId::of(derivable_impls::DERIVABLE_IMPLS),
-    LintId::of(double_parens::DOUBLE_PARENS),
-    LintId::of(explicit_write::EXPLICIT_WRITE),
-    LintId::of(format::USELESS_FORMAT),
-    LintId::of(format_args::UNUSED_FORMAT_SPECS),
-    LintId::of(functions::TOO_MANY_ARGUMENTS),
-    LintId::of(int_plus_one::INT_PLUS_ONE),
-    LintId::of(lifetimes::EXTRA_UNUSED_LIFETIMES),
-    LintId::of(lifetimes::NEEDLESS_LIFETIMES),
-    LintId::of(loops::EXPLICIT_COUNTER_LOOP),
-    LintId::of(loops::MANUAL_FIND),
-    LintId::of(loops::MANUAL_FLATTEN),
-    LintId::of(loops::SINGLE_ELEMENT_LOOP),
-    LintId::of(loops::WHILE_LET_LOOP),
-    LintId::of(manual_clamp::MANUAL_CLAMP),
-    LintId::of(manual_rem_euclid::MANUAL_REM_EUCLID),
-    LintId::of(manual_strip::MANUAL_STRIP),
-    LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN),
-    LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN),
-    LintId::of(matches::MANUAL_FILTER),
-    LintId::of(matches::MANUAL_UNWRAP_OR),
-    LintId::of(matches::MATCH_AS_REF),
-    LintId::of(matches::MATCH_SINGLE_BINDING),
-    LintId::of(matches::NEEDLESS_MATCH),
-    LintId::of(matches::WILDCARD_IN_OR_PATTERNS),
-    LintId::of(methods::BIND_INSTEAD_OF_MAP),
-    LintId::of(methods::BYTES_COUNT_TO_LEN),
-    LintId::of(methods::CLONE_ON_COPY),
-    LintId::of(methods::FILTER_MAP_IDENTITY),
-    LintId::of(methods::FILTER_NEXT),
-    LintId::of(methods::FLAT_MAP_IDENTITY),
-    LintId::of(methods::GET_LAST_WITH_LEN),
-    LintId::of(methods::INSPECT_FOR_EACH),
-    LintId::of(methods::ITER_COUNT),
-    LintId::of(methods::ITER_KV_MAP),
-    LintId::of(methods::MANUAL_FILTER_MAP),
-    LintId::of(methods::MANUAL_FIND_MAP),
-    LintId::of(methods::MANUAL_SPLIT_ONCE),
-    LintId::of(methods::MAP_FLATTEN),
-    LintId::of(methods::MAP_IDENTITY),
-    LintId::of(methods::NEEDLESS_OPTION_AS_DEREF),
-    LintId::of(methods::NEEDLESS_OPTION_TAKE),
-    LintId::of(methods::NEEDLESS_SPLITN),
-    LintId::of(methods::OPTION_AS_REF_DEREF),
-    LintId::of(methods::OPTION_FILTER_MAP),
-    LintId::of(methods::OR_THEN_UNWRAP),
-    LintId::of(methods::RANGE_ZIP_WITH_LEN),
-    LintId::of(methods::REPEAT_ONCE),
-    LintId::of(methods::SEARCH_IS_SOME),
-    LintId::of(methods::SKIP_WHILE_NEXT),
-    LintId::of(methods::UNNECESSARY_FILTER_MAP),
-    LintId::of(methods::UNNECESSARY_FIND_MAP),
-    LintId::of(methods::UNNECESSARY_SORT_BY),
-    LintId::of(methods::USELESS_ASREF),
-    LintId::of(misc::SHORT_CIRCUIT_STATEMENT),
-    LintId::of(misc_early::UNNEEDED_WILDCARD_PATTERN),
-    LintId::of(misc_early::ZERO_PREFIXED_LITERAL),
-    LintId::of(mixed_read_write_in_expression::DIVERGING_SUB_EXPRESSION),
-    LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE),
-    LintId::of(needless_bool::BOOL_COMPARISON),
-    LintId::of(needless_bool::NEEDLESS_BOOL),
-    LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
-    LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK),
-    LintId::of(needless_update::NEEDLESS_UPDATE),
-    LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD),
-    LintId::of(no_effect::NO_EFFECT),
-    LintId::of(no_effect::UNNECESSARY_OPERATION),
-    LintId::of(only_used_in_recursion::ONLY_USED_IN_RECURSION),
-    LintId::of(operators::DOUBLE_COMPARISONS),
-    LintId::of(operators::DURATION_SUBSEC),
-    LintId::of(operators::IDENTITY_OP),
-    LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
-    LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
-    LintId::of(precedence::PRECEDENCE),
-    LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
-    LintId::of(redundant_closure_call::REDUNDANT_CLOSURE_CALL),
-    LintId::of(redundant_slicing::REDUNDANT_SLICING),
-    LintId::of(reference::DEREF_ADDROF),
-    LintId::of(strings::STRING_FROM_UTF8_AS_BYTES),
-    LintId::of(strlen_on_c_strings::STRLEN_ON_C_STRINGS),
-    LintId::of(swap::MANUAL_SWAP),
-    LintId::of(temporary_assignment::TEMPORARY_ASSIGNMENT),
-    LintId::of(transmute::CROSSPOINTER_TRANSMUTE),
-    LintId::of(transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS),
-    LintId::of(transmute::TRANSMUTE_BYTES_TO_STR),
-    LintId::of(transmute::TRANSMUTE_FLOAT_TO_INT),
-    LintId::of(transmute::TRANSMUTE_INT_TO_BOOL),
-    LintId::of(transmute::TRANSMUTE_INT_TO_CHAR),
-    LintId::of(transmute::TRANSMUTE_INT_TO_FLOAT),
-    LintId::of(transmute::TRANSMUTE_NUM_TO_BYTES),
-    LintId::of(transmute::TRANSMUTE_PTR_TO_REF),
-    LintId::of(transmute::USELESS_TRANSMUTE),
-    LintId::of(types::BORROWED_BOX),
-    LintId::of(types::TYPE_COMPLEXITY),
-    LintId::of(types::VEC_BOX),
-    LintId::of(unit_types::UNIT_ARG),
-    LintId::of(unwrap::UNNECESSARY_UNWRAP),
-    LintId::of(useless_conversion::USELESS_CONVERSION),
-    LintId::of(zero_div_zero::ZERO_DIVIDED_BY_ZERO),
-])
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs
deleted file mode 100644
index bb94037ec2e..00000000000
--- a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-// This file was generated by `cargo dev update_lints`.
-// Use that command to update this file and do not edit by hand.
-// Manual edits will be overwritten.
-
-store.register_group(true, "clippy::correctness", Some("clippy_correctness"), vec![
-    LintId::of(approx_const::APPROX_CONSTANT),
-    LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC),
-    LintId::of(attrs::DEPRECATED_SEMVER),
-    LintId::of(attrs::MISMATCHED_TARGET_OS),
-    LintId::of(attrs::USELESS_ATTRIBUTE),
-    LintId::of(booleans::OVERLY_COMPLEX_BOOL_EXPR),
-    LintId::of(casts::CAST_REF_TO_MUT),
-    LintId::of(casts::CAST_SLICE_DIFFERENT_SIZES),
-    LintId::of(copies::IFS_SAME_COND),
-    LintId::of(copies::IF_SAME_THEN_ELSE),
-    LintId::of(derive::DERIVE_HASH_XOR_EQ),
-    LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD),
-    LintId::of(drop_forget_ref::DROP_COPY),
-    LintId::of(drop_forget_ref::DROP_REF),
-    LintId::of(drop_forget_ref::FORGET_COPY),
-    LintId::of(drop_forget_ref::FORGET_REF),
-    LintId::of(drop_forget_ref::UNDROPPED_MANUALLY_DROPS),
-    LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT),
-    LintId::of(format_impl::RECURSIVE_FORMAT_IMPL),
-    LintId::of(formatting::POSSIBLE_MISSING_COMMA),
-    LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF),
-    LintId::of(if_let_mutex::IF_LET_MUTEX),
-    LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING),
-    LintId::of(infinite_iter::INFINITE_ITER),
-    LintId::of(inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
-    LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
-    LintId::of(invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED),
-    LintId::of(let_underscore::LET_UNDERSCORE_LOCK),
-    LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES),
-    LintId::of(loops::ITER_NEXT_LOOP),
-    LintId::of(loops::NEVER_LOOP),
-    LintId::of(loops::WHILE_IMMUTABLE_CONDITION),
-    LintId::of(matches::MATCH_STR_CASE_MISMATCH),
-    LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT),
-    LintId::of(methods::CLONE_DOUBLE_REF),
-    LintId::of(methods::ITERATOR_STEP_BY_ZERO),
-    LintId::of(methods::NONSENSICAL_OPEN_OPTIONS),
-    LintId::of(methods::SUSPICIOUS_SPLITN),
-    LintId::of(methods::UNINIT_ASSUMED_INIT),
-    LintId::of(methods::UNIT_HASH),
-    LintId::of(methods::VEC_RESIZE_TO_ZERO),
-    LintId::of(methods::ZST_OFFSET),
-    LintId::of(minmax::MIN_MAX),
-    LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS),
-    LintId::of(operators::ABSURD_EXTREME_COMPARISONS),
-    LintId::of(operators::BAD_BIT_MASK),
-    LintId::of(operators::CMP_NAN),
-    LintId::of(operators::EQ_OP),
-    LintId::of(operators::ERASING_OP),
-    LintId::of(operators::INEFFECTIVE_BIT_MASK),
-    LintId::of(operators::MODULO_ONE),
-    LintId::of(operators::SELF_ASSIGNMENT),
-    LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
-    LintId::of(ptr::INVALID_NULL_PTR_USAGE),
-    LintId::of(ptr::MUT_FROM_REF),
-    LintId::of(ranges::REVERSED_EMPTY_RANGES),
-    LintId::of(read_zero_byte_vec::READ_ZERO_BYTE_VEC),
-    LintId::of(regex::INVALID_REGEX),
-    LintId::of(serde_api::SERDE_API_MISUSE),
-    LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
-    LintId::of(swap::ALMOST_SWAPPED),
-    LintId::of(transmute::TRANSMUTING_NULL),
-    LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE),
-    LintId::of(transmute::WRONG_TRANSMUTE),
-    LintId::of(unicode::INVISIBLE_CHARACTERS),
-    LintId::of(uninit_vec::UNINIT_VEC),
-    LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
-    LintId::of(unit_types::UNIT_CMP),
-    LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS),
-    LintId::of(unnamed_address::VTABLE_ADDRESS_COMPARISONS),
-    LintId::of(unused_io_amount::UNUSED_IO_AMOUNT),
-    LintId::of(unwrap::PANICKING_UNWRAP),
-])
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_internal.rs b/src/tools/clippy/clippy_lints/src/lib.register_internal.rs
deleted file mode 100644
index 40c94c6e8d3..00000000000
--- a/src/tools/clippy/clippy_lints/src/lib.register_internal.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-// This file was generated by `cargo dev update_lints`.
-// Use that command to update this file and do not edit by hand.
-// Manual edits will be overwritten.
-
-store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![
-    LintId::of(utils::internal_lints::clippy_lints_internal::CLIPPY_LINTS_INTERNAL),
-    LintId::of(utils::internal_lints::collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS),
-    LintId::of(utils::internal_lints::compiler_lint_functions::COMPILER_LINT_FUNCTIONS),
-    LintId::of(utils::internal_lints::if_chain_style::IF_CHAIN_STYLE),
-    LintId::of(utils::internal_lints::interning_defined_symbol::INTERNING_DEFINED_SYMBOL),
-    LintId::of(utils::internal_lints::interning_defined_symbol::UNNECESSARY_SYMBOL_STR),
-    LintId::of(utils::internal_lints::invalid_paths::INVALID_PATHS),
-    LintId::of(utils::internal_lints::lint_without_lint_pass::DEFAULT_DEPRECATION_REASON),
-    LintId::of(utils::internal_lints::lint_without_lint_pass::DEFAULT_LINT),
-    LintId::of(utils::internal_lints::lint_without_lint_pass::INVALID_CLIPPY_VERSION_ATTRIBUTE),
-    LintId::of(utils::internal_lints::lint_without_lint_pass::LINT_WITHOUT_LINT_PASS),
-    LintId::of(utils::internal_lints::lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE),
-    LintId::of(utils::internal_lints::msrv_attr_impl::MISSING_MSRV_ATTR_IMPL),
-    LintId::of(utils::internal_lints::outer_expn_data_pass::OUTER_EXPN_EXPN_DATA),
-    LintId::of(utils::internal_lints::produce_ice::PRODUCE_ICE),
-    LintId::of(utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH),
-])
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs
deleted file mode 100644
index 800e3a87671..00000000000
--- a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs
+++ /dev/null
@@ -1,620 +0,0 @@
-// This file was generated by `cargo dev update_lints`.
-// Use that command to update this file and do not edit by hand.
-// Manual edits will be overwritten.
-
-store.register_lints(&[
-    #[cfg(feature = "internal")]
-    utils::internal_lints::clippy_lints_internal::CLIPPY_LINTS_INTERNAL,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::compiler_lint_functions::COMPILER_LINT_FUNCTIONS,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::if_chain_style::IF_CHAIN_STYLE,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::interning_defined_symbol::INTERNING_DEFINED_SYMBOL,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::interning_defined_symbol::UNNECESSARY_SYMBOL_STR,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::invalid_paths::INVALID_PATHS,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::lint_without_lint_pass::DEFAULT_DEPRECATION_REASON,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::lint_without_lint_pass::DEFAULT_LINT,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::lint_without_lint_pass::INVALID_CLIPPY_VERSION_ATTRIBUTE,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::lint_without_lint_pass::LINT_WITHOUT_LINT_PASS,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::msrv_attr_impl::MISSING_MSRV_ATTR_IMPL,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::outer_expn_data_pass::OUTER_EXPN_EXPN_DATA,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::produce_ice::PRODUCE_ICE,
-    #[cfg(feature = "internal")]
-    utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH,
-    almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE,
-    approx_const::APPROX_CONSTANT,
-    as_conversions::AS_CONVERSIONS,
-    asm_syntax::INLINE_ASM_X86_ATT_SYNTAX,
-    asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX,
-    assertions_on_constants::ASSERTIONS_ON_CONSTANTS,
-    assertions_on_result_states::ASSERTIONS_ON_RESULT_STATES,
-    async_yields_async::ASYNC_YIELDS_ASYNC,
-    attrs::ALLOW_ATTRIBUTES_WITHOUT_REASON,
-    attrs::BLANKET_CLIPPY_RESTRICTION_LINTS,
-    attrs::DEPRECATED_CFG_ATTR,
-    attrs::DEPRECATED_SEMVER,
-    attrs::EMPTY_LINE_AFTER_OUTER_ATTR,
-    attrs::INLINE_ALWAYS,
-    attrs::MISMATCHED_TARGET_OS,
-    attrs::USELESS_ATTRIBUTE,
-    await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE,
-    await_holding_invalid::AWAIT_HOLDING_LOCK,
-    await_holding_invalid::AWAIT_HOLDING_REFCELL_REF,
-    blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS,
-    bool_assert_comparison::BOOL_ASSERT_COMPARISON,
-    bool_to_int_with_if::BOOL_TO_INT_WITH_IF,
-    booleans::NONMINIMAL_BOOL,
-    booleans::OVERLY_COMPLEX_BOOL_EXPR,
-    borrow_deref_ref::BORROW_DEREF_REF,
-    box_default::BOX_DEFAULT,
-    cargo::CARGO_COMMON_METADATA,
-    cargo::MULTIPLE_CRATE_VERSIONS,
-    cargo::NEGATIVE_FEATURE_NAMES,
-    cargo::REDUNDANT_FEATURE_NAMES,
-    cargo::WILDCARD_DEPENDENCIES,
-    casts::AS_PTR_CAST_MUT,
-    casts::AS_UNDERSCORE,
-    casts::BORROW_AS_PTR,
-    casts::CAST_ABS_TO_UNSIGNED,
-    casts::CAST_ENUM_CONSTRUCTOR,
-    casts::CAST_ENUM_TRUNCATION,
-    casts::CAST_LOSSLESS,
-    casts::CAST_NAN_TO_INT,
-    casts::CAST_POSSIBLE_TRUNCATION,
-    casts::CAST_POSSIBLE_WRAP,
-    casts::CAST_PRECISION_LOSS,
-    casts::CAST_PTR_ALIGNMENT,
-    casts::CAST_REF_TO_MUT,
-    casts::CAST_SIGN_LOSS,
-    casts::CAST_SLICE_DIFFERENT_SIZES,
-    casts::CAST_SLICE_FROM_RAW_PARTS,
-    casts::CHAR_LIT_AS_U8,
-    casts::FN_TO_NUMERIC_CAST,
-    casts::FN_TO_NUMERIC_CAST_ANY,
-    casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
-    casts::PTR_AS_PTR,
-    casts::UNNECESSARY_CAST,
-    checked_conversions::CHECKED_CONVERSIONS,
-    cognitive_complexity::COGNITIVE_COMPLEXITY,
-    collapsible_if::COLLAPSIBLE_ELSE_IF,
-    collapsible_if::COLLAPSIBLE_IF,
-    comparison_chain::COMPARISON_CHAIN,
-    copies::BRANCHES_SHARING_CODE,
-    copies::IFS_SAME_COND,
-    copies::IF_SAME_THEN_ELSE,
-    copies::SAME_FUNCTIONS_IN_IF_CONDITION,
-    copy_iterator::COPY_ITERATOR,
-    crate_in_macro_def::CRATE_IN_MACRO_DEF,
-    create_dir::CREATE_DIR,
-    dbg_macro::DBG_MACRO,
-    default::DEFAULT_TRAIT_ACCESS,
-    default::FIELD_REASSIGN_WITH_DEFAULT,
-    default_instead_of_iter_empty::DEFAULT_INSTEAD_OF_ITER_EMPTY,
-    default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK,
-    default_union_representation::DEFAULT_UNION_REPRESENTATION,
-    dereference::EXPLICIT_AUTO_DEREF,
-    dereference::EXPLICIT_DEREF_METHODS,
-    dereference::NEEDLESS_BORROW,
-    dereference::REF_BINDING_TO_REFERENCE,
-    derivable_impls::DERIVABLE_IMPLS,
-    derive::DERIVE_HASH_XOR_EQ,
-    derive::DERIVE_ORD_XOR_PARTIAL_ORD,
-    derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ,
-    derive::EXPL_IMPL_CLONE_ON_COPY,
-    derive::UNSAFE_DERIVE_DESERIALIZE,
-    disallowed_macros::DISALLOWED_MACROS,
-    disallowed_methods::DISALLOWED_METHODS,
-    disallowed_names::DISALLOWED_NAMES,
-    disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS,
-    disallowed_types::DISALLOWED_TYPES,
-    doc::DOC_LINK_WITH_QUOTES,
-    doc::DOC_MARKDOWN,
-    doc::MISSING_ERRORS_DOC,
-    doc::MISSING_PANICS_DOC,
-    doc::MISSING_SAFETY_DOC,
-    doc::NEEDLESS_DOCTEST_MAIN,
-    double_parens::DOUBLE_PARENS,
-    drop_forget_ref::DROP_COPY,
-    drop_forget_ref::DROP_NON_DROP,
-    drop_forget_ref::DROP_REF,
-    drop_forget_ref::FORGET_COPY,
-    drop_forget_ref::FORGET_NON_DROP,
-    drop_forget_ref::FORGET_REF,
-    drop_forget_ref::UNDROPPED_MANUALLY_DROPS,
-    duplicate_mod::DUPLICATE_MOD,
-    else_if_without_else::ELSE_IF_WITHOUT_ELSE,
-    empty_drop::EMPTY_DROP,
-    empty_enum::EMPTY_ENUM,
-    empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS,
-    entry::MAP_ENTRY,
-    enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT,
-    enum_variants::ENUM_VARIANT_NAMES,
-    enum_variants::MODULE_INCEPTION,
-    enum_variants::MODULE_NAME_REPETITIONS,
-    equatable_if_let::EQUATABLE_IF_LET,
-    escape::BOXED_LOCAL,
-    eta_reduction::REDUNDANT_CLOSURE,
-    eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS,
-    excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS,
-    excessive_bools::STRUCT_EXCESSIVE_BOOLS,
-    exhaustive_items::EXHAUSTIVE_ENUMS,
-    exhaustive_items::EXHAUSTIVE_STRUCTS,
-    exit::EXIT,
-    explicit_write::EXPLICIT_WRITE,
-    fallible_impl_from::FALLIBLE_IMPL_FROM,
-    float_literal::EXCESSIVE_PRECISION,
-    float_literal::LOSSY_FLOAT_LITERAL,
-    floating_point_arithmetic::IMPRECISE_FLOPS,
-    floating_point_arithmetic::SUBOPTIMAL_FLOPS,
-    format::USELESS_FORMAT,
-    format_args::FORMAT_IN_FORMAT_ARGS,
-    format_args::TO_STRING_IN_FORMAT_ARGS,
-    format_args::UNINLINED_FORMAT_ARGS,
-    format_args::UNUSED_FORMAT_SPECS,
-    format_impl::PRINT_IN_FORMAT_IMPL,
-    format_impl::RECURSIVE_FORMAT_IMPL,
-    format_push_string::FORMAT_PUSH_STRING,
-    formatting::POSSIBLE_MISSING_COMMA,
-    formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING,
-    formatting::SUSPICIOUS_ELSE_FORMATTING,
-    formatting::SUSPICIOUS_UNARY_OP_FORMATTING,
-    from_over_into::FROM_OVER_INTO,
-    from_str_radix_10::FROM_STR_RADIX_10,
-    functions::DOUBLE_MUST_USE,
-    functions::MUST_USE_CANDIDATE,
-    functions::MUST_USE_UNIT,
-    functions::NOT_UNSAFE_PTR_ARG_DEREF,
-    functions::RESULT_LARGE_ERR,
-    functions::RESULT_UNIT_ERR,
-    functions::TOO_MANY_ARGUMENTS,
-    functions::TOO_MANY_LINES,
-    future_not_send::FUTURE_NOT_SEND,
-    if_let_mutex::IF_LET_MUTEX,
-    if_not_else::IF_NOT_ELSE,
-    if_then_some_else_none::IF_THEN_SOME_ELSE_NONE,
-    implicit_hasher::IMPLICIT_HASHER,
-    implicit_return::IMPLICIT_RETURN,
-    implicit_saturating_add::IMPLICIT_SATURATING_ADD,
-    implicit_saturating_sub::IMPLICIT_SATURATING_SUB,
-    inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR,
-    index_refutable_slice::INDEX_REFUTABLE_SLICE,
-    indexing_slicing::INDEXING_SLICING,
-    indexing_slicing::OUT_OF_BOUNDS_INDEXING,
-    infinite_iter::INFINITE_ITER,
-    infinite_iter::MAYBE_INFINITE_ITER,
-    inherent_impl::MULTIPLE_INHERENT_IMPL,
-    inherent_to_string::INHERENT_TO_STRING,
-    inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY,
-    init_numbered_fields::INIT_NUMBERED_FIELDS,
-    inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
-    int_plus_one::INT_PLUS_ONE,
-    invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS,
-    invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED,
-    items_after_statements::ITEMS_AFTER_STATEMENTS,
-    iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR,
-    large_const_arrays::LARGE_CONST_ARRAYS,
-    large_enum_variant::LARGE_ENUM_VARIANT,
-    large_include_file::LARGE_INCLUDE_FILE,
-    large_stack_arrays::LARGE_STACK_ARRAYS,
-    len_zero::COMPARISON_TO_EMPTY,
-    len_zero::LEN_WITHOUT_IS_EMPTY,
-    len_zero::LEN_ZERO,
-    let_if_seq::USELESS_LET_IF_SEQ,
-    let_underscore::LET_UNDERSCORE_DROP,
-    let_underscore::LET_UNDERSCORE_LOCK,
-    let_underscore::LET_UNDERSCORE_MUST_USE,
-    lifetimes::EXTRA_UNUSED_LIFETIMES,
-    lifetimes::NEEDLESS_LIFETIMES,
-    literal_representation::DECIMAL_LITERAL_REPRESENTATION,
-    literal_representation::INCONSISTENT_DIGIT_GROUPING,
-    literal_representation::LARGE_DIGIT_GROUPS,
-    literal_representation::MISTYPED_LITERAL_SUFFIXES,
-    literal_representation::UNREADABLE_LITERAL,
-    literal_representation::UNUSUAL_BYTE_GROUPINGS,
-    loops::EMPTY_LOOP,
-    loops::EXPLICIT_COUNTER_LOOP,
-    loops::EXPLICIT_INTO_ITER_LOOP,
-    loops::EXPLICIT_ITER_LOOP,
-    loops::FOR_KV_MAP,
-    loops::ITER_NEXT_LOOP,
-    loops::MANUAL_FIND,
-    loops::MANUAL_FLATTEN,
-    loops::MANUAL_MEMCPY,
-    loops::MISSING_SPIN_LOOP,
-    loops::MUT_RANGE_BOUND,
-    loops::NEEDLESS_COLLECT,
-    loops::NEEDLESS_RANGE_LOOP,
-    loops::NEVER_LOOP,
-    loops::SAME_ITEM_PUSH,
-    loops::SINGLE_ELEMENT_LOOP,
-    loops::WHILE_IMMUTABLE_CONDITION,
-    loops::WHILE_LET_LOOP,
-    loops::WHILE_LET_ON_ITERATOR,
-    macro_use::MACRO_USE_IMPORTS,
-    main_recursion::MAIN_RECURSION,
-    manual_assert::MANUAL_ASSERT,
-    manual_async_fn::MANUAL_ASYNC_FN,
-    manual_bits::MANUAL_BITS,
-    manual_clamp::MANUAL_CLAMP,
-    manual_instant_elapsed::MANUAL_INSTANT_ELAPSED,
-    manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE,
-    manual_rem_euclid::MANUAL_REM_EUCLID,
-    manual_retain::MANUAL_RETAIN,
-    manual_string_new::MANUAL_STRING_NEW,
-    manual_strip::MANUAL_STRIP,
-    map_unit_fn::OPTION_MAP_UNIT_FN,
-    map_unit_fn::RESULT_MAP_UNIT_FN,
-    match_result_ok::MATCH_RESULT_OK,
-    matches::COLLAPSIBLE_MATCH,
-    matches::INFALLIBLE_DESTRUCTURING_MATCH,
-    matches::MANUAL_FILTER,
-    matches::MANUAL_MAP,
-    matches::MANUAL_UNWRAP_OR,
-    matches::MATCH_AS_REF,
-    matches::MATCH_BOOL,
-    matches::MATCH_LIKE_MATCHES_MACRO,
-    matches::MATCH_ON_VEC_ITEMS,
-    matches::MATCH_OVERLAPPING_ARM,
-    matches::MATCH_REF_PATS,
-    matches::MATCH_SAME_ARMS,
-    matches::MATCH_SINGLE_BINDING,
-    matches::MATCH_STR_CASE_MISMATCH,
-    matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
-    matches::MATCH_WILD_ERR_ARM,
-    matches::NEEDLESS_MATCH,
-    matches::REDUNDANT_PATTERN_MATCHING,
-    matches::REST_PAT_IN_FULLY_BOUND_STRUCTS,
-    matches::SIGNIFICANT_DROP_IN_SCRUTINEE,
-    matches::SINGLE_MATCH,
-    matches::SINGLE_MATCH_ELSE,
-    matches::TRY_ERR,
-    matches::WILDCARD_ENUM_MATCH_ARM,
-    matches::WILDCARD_IN_OR_PATTERNS,
-    mem_forget::MEM_FORGET,
-    mem_replace::MEM_REPLACE_OPTION_WITH_NONE,
-    mem_replace::MEM_REPLACE_WITH_DEFAULT,
-    mem_replace::MEM_REPLACE_WITH_UNINIT,
-    methods::BIND_INSTEAD_OF_MAP,
-    methods::BYTES_COUNT_TO_LEN,
-    methods::BYTES_NTH,
-    methods::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,
-    methods::CHARS_LAST_CMP,
-    methods::CHARS_NEXT_CMP,
-    methods::CLONED_INSTEAD_OF_COPIED,
-    methods::CLONE_DOUBLE_REF,
-    methods::CLONE_ON_COPY,
-    methods::CLONE_ON_REF_PTR,
-    methods::COLLAPSIBLE_STR_REPLACE,
-    methods::ERR_EXPECT,
-    methods::EXPECT_FUN_CALL,
-    methods::EXPECT_USED,
-    methods::EXTEND_WITH_DRAIN,
-    methods::FILETYPE_IS_FILE,
-    methods::FILTER_MAP_IDENTITY,
-    methods::FILTER_MAP_NEXT,
-    methods::FILTER_NEXT,
-    methods::FLAT_MAP_IDENTITY,
-    methods::FLAT_MAP_OPTION,
-    methods::FROM_ITER_INSTEAD_OF_COLLECT,
-    methods::GET_FIRST,
-    methods::GET_LAST_WITH_LEN,
-    methods::GET_UNWRAP,
-    methods::IMPLICIT_CLONE,
-    methods::INEFFICIENT_TO_STRING,
-    methods::INSPECT_FOR_EACH,
-    methods::INTO_ITER_ON_REF,
-    methods::IS_DIGIT_ASCII_RADIX,
-    methods::ITERATOR_STEP_BY_ZERO,
-    methods::ITER_CLONED_COLLECT,
-    methods::ITER_COUNT,
-    methods::ITER_KV_MAP,
-    methods::ITER_NEXT_SLICE,
-    methods::ITER_NTH,
-    methods::ITER_NTH_ZERO,
-    methods::ITER_ON_EMPTY_COLLECTIONS,
-    methods::ITER_ON_SINGLE_ITEMS,
-    methods::ITER_OVEREAGER_CLONED,
-    methods::ITER_SKIP_NEXT,
-    methods::ITER_WITH_DRAIN,
-    methods::MANUAL_FILTER_MAP,
-    methods::MANUAL_FIND_MAP,
-    methods::MANUAL_OK_OR,
-    methods::MANUAL_SATURATING_ARITHMETIC,
-    methods::MANUAL_SPLIT_ONCE,
-    methods::MANUAL_STR_REPEAT,
-    methods::MAP_CLONE,
-    methods::MAP_COLLECT_RESULT_UNIT,
-    methods::MAP_ERR_IGNORE,
-    methods::MAP_FLATTEN,
-    methods::MAP_IDENTITY,
-    methods::MAP_UNWRAP_OR,
-    methods::MUT_MUTEX_LOCK,
-    methods::NAIVE_BYTECOUNT,
-    methods::NEEDLESS_OPTION_AS_DEREF,
-    methods::NEEDLESS_OPTION_TAKE,
-    methods::NEEDLESS_SPLITN,
-    methods::NEW_RET_NO_SELF,
-    methods::NONSENSICAL_OPEN_OPTIONS,
-    methods::NO_EFFECT_REPLACE,
-    methods::OBFUSCATED_IF_ELSE,
-    methods::OK_EXPECT,
-    methods::OPTION_AS_REF_DEREF,
-    methods::OPTION_FILTER_MAP,
-    methods::OPTION_MAP_OR_NONE,
-    methods::OR_FUN_CALL,
-    methods::OR_THEN_UNWRAP,
-    methods::PATH_BUF_PUSH_OVERWRITE,
-    methods::RANGE_ZIP_WITH_LEN,
-    methods::REPEAT_ONCE,
-    methods::RESULT_MAP_OR_INTO_OPTION,
-    methods::SEARCH_IS_SOME,
-    methods::SHOULD_IMPLEMENT_TRAIT,
-    methods::SINGLE_CHAR_ADD_STR,
-    methods::SINGLE_CHAR_PATTERN,
-    methods::SKIP_WHILE_NEXT,
-    methods::STABLE_SORT_PRIMITIVE,
-    methods::STRING_EXTEND_CHARS,
-    methods::SUSPICIOUS_MAP,
-    methods::SUSPICIOUS_SPLITN,
-    methods::SUSPICIOUS_TO_OWNED,
-    methods::UNINIT_ASSUMED_INIT,
-    methods::UNIT_HASH,
-    methods::UNNECESSARY_FILTER_MAP,
-    methods::UNNECESSARY_FIND_MAP,
-    methods::UNNECESSARY_FOLD,
-    methods::UNNECESSARY_JOIN,
-    methods::UNNECESSARY_LAZY_EVALUATIONS,
-    methods::UNNECESSARY_SORT_BY,
-    methods::UNNECESSARY_TO_OWNED,
-    methods::UNWRAP_OR_ELSE_DEFAULT,
-    methods::UNWRAP_USED,
-    methods::USELESS_ASREF,
-    methods::VEC_RESIZE_TO_ZERO,
-    methods::VERBOSE_FILE_READS,
-    methods::WRONG_SELF_CONVENTION,
-    methods::ZST_OFFSET,
-    minmax::MIN_MAX,
-    misc::SHORT_CIRCUIT_STATEMENT,
-    misc::TOPLEVEL_REF_ARG,
-    misc::USED_UNDERSCORE_BINDING,
-    misc::ZERO_PTR,
-    misc_early::BUILTIN_TYPE_SHADOW,
-    misc_early::DOUBLE_NEG,
-    misc_early::DUPLICATE_UNDERSCORE_ARGUMENT,
-    misc_early::MIXED_CASE_HEX_LITERALS,
-    misc_early::REDUNDANT_PATTERN,
-    misc_early::SEPARATED_LITERAL_SUFFIX,
-    misc_early::UNNEEDED_FIELD_PATTERN,
-    misc_early::UNNEEDED_WILDCARD_PATTERN,
-    misc_early::UNSEPARATED_LITERAL_SUFFIX,
-    misc_early::ZERO_PREFIXED_LITERAL,
-    mismatching_type_param_order::MISMATCHING_TYPE_PARAM_ORDER,
-    missing_const_for_fn::MISSING_CONST_FOR_FN,
-    missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS,
-    missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES,
-    missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS,
-    missing_trait_methods::MISSING_TRAIT_METHODS,
-    mixed_read_write_in_expression::DIVERGING_SUB_EXPRESSION,
-    mixed_read_write_in_expression::MIXED_READ_WRITE_IN_EXPRESSION,
-    module_style::MOD_MODULE_FILES,
-    module_style::SELF_NAMED_MODULE_FILES,
-    multi_assignments::MULTI_ASSIGNMENTS,
-    mut_key::MUTABLE_KEY_TYPE,
-    mut_mut::MUT_MUT,
-    mut_reference::UNNECESSARY_MUT_PASSED,
-    mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL,
-    mutex_atomic::MUTEX_ATOMIC,
-    mutex_atomic::MUTEX_INTEGER,
-    needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE,
-    needless_bool::BOOL_COMPARISON,
-    needless_bool::NEEDLESS_BOOL,
-    needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE,
-    needless_continue::NEEDLESS_CONTINUE,
-    needless_for_each::NEEDLESS_FOR_EACH,
-    needless_late_init::NEEDLESS_LATE_INIT,
-    needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS,
-    needless_pass_by_value::NEEDLESS_PASS_BY_VALUE,
-    needless_question_mark::NEEDLESS_QUESTION_MARK,
-    needless_update::NEEDLESS_UPDATE,
-    neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD,
-    neg_multiply::NEG_MULTIPLY,
-    new_without_default::NEW_WITHOUT_DEFAULT,
-    no_effect::NO_EFFECT,
-    no_effect::NO_EFFECT_UNDERSCORE_BINDING,
-    no_effect::UNNECESSARY_OPERATION,
-    non_copy_const::BORROW_INTERIOR_MUTABLE_CONST,
-    non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST,
-    non_expressive_names::JUST_UNDERSCORES_AND_DIGITS,
-    non_expressive_names::MANY_SINGLE_CHAR_NAMES,
-    non_expressive_names::SIMILAR_NAMES,
-    non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS,
-    non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY,
-    nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES,
-    octal_escapes::OCTAL_ESCAPES,
-    only_used_in_recursion::ONLY_USED_IN_RECURSION,
-    operators::ABSURD_EXTREME_COMPARISONS,
-    operators::ARITHMETIC_SIDE_EFFECTS,
-    operators::ASSIGN_OP_PATTERN,
-    operators::BAD_BIT_MASK,
-    operators::CMP_NAN,
-    operators::CMP_OWNED,
-    operators::DOUBLE_COMPARISONS,
-    operators::DURATION_SUBSEC,
-    operators::EQ_OP,
-    operators::ERASING_OP,
-    operators::FLOAT_ARITHMETIC,
-    operators::FLOAT_CMP,
-    operators::FLOAT_CMP_CONST,
-    operators::FLOAT_EQUALITY_WITHOUT_ABS,
-    operators::IDENTITY_OP,
-    operators::INEFFECTIVE_BIT_MASK,
-    operators::INTEGER_ARITHMETIC,
-    operators::INTEGER_DIVISION,
-    operators::MISREFACTORED_ASSIGN_OP,
-    operators::MODULO_ARITHMETIC,
-    operators::MODULO_ONE,
-    operators::NEEDLESS_BITWISE_BOOL,
-    operators::OP_REF,
-    operators::PTR_EQ,
-    operators::SELF_ASSIGNMENT,
-    operators::VERBOSE_BIT_MASK,
-    option_env_unwrap::OPTION_ENV_UNWRAP,
-    option_if_let_else::OPTION_IF_LET_ELSE,
-    overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL,
-    panic_in_result_fn::PANIC_IN_RESULT_FN,
-    panic_unimplemented::PANIC,
-    panic_unimplemented::TODO,
-    panic_unimplemented::UNIMPLEMENTED,
-    panic_unimplemented::UNREACHABLE,
-    partial_pub_fields::PARTIAL_PUB_FIELDS,
-    partialeq_ne_impl::PARTIALEQ_NE_IMPL,
-    partialeq_to_none::PARTIALEQ_TO_NONE,
-    pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE,
-    pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF,
-    pattern_type_mismatch::PATTERN_TYPE_MISMATCH,
-    precedence::PRECEDENCE,
-    ptr::CMP_NULL,
-    ptr::INVALID_NULL_PTR_USAGE,
-    ptr::MUT_FROM_REF,
-    ptr::PTR_ARG,
-    ptr_offset_with_cast::PTR_OFFSET_WITH_CAST,
-    pub_use::PUB_USE,
-    question_mark::QUESTION_MARK,
-    ranges::MANUAL_RANGE_CONTAINS,
-    ranges::RANGE_MINUS_ONE,
-    ranges::RANGE_PLUS_ONE,
-    ranges::REVERSED_EMPTY_RANGES,
-    rc_clone_in_vec_init::RC_CLONE_IN_VEC_INIT,
-    read_zero_byte_vec::READ_ZERO_BYTE_VEC,
-    redundant_clone::REDUNDANT_CLONE,
-    redundant_closure_call::REDUNDANT_CLOSURE_CALL,
-    redundant_else::REDUNDANT_ELSE,
-    redundant_field_names::REDUNDANT_FIELD_NAMES,
-    redundant_pub_crate::REDUNDANT_PUB_CRATE,
-    redundant_slicing::DEREF_BY_SLICING,
-    redundant_slicing::REDUNDANT_SLICING,
-    redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES,
-    ref_option_ref::REF_OPTION_REF,
-    reference::DEREF_ADDROF,
-    regex::INVALID_REGEX,
-    regex::TRIVIAL_REGEX,
-    return_self_not_must_use::RETURN_SELF_NOT_MUST_USE,
-    returns::LET_AND_RETURN,
-    returns::NEEDLESS_RETURN,
-    same_name_method::SAME_NAME_METHOD,
-    self_named_constructors::SELF_NAMED_CONSTRUCTORS,
-    semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED,
-    serde_api::SERDE_API_MISUSE,
-    shadow::SHADOW_REUSE,
-    shadow::SHADOW_SAME,
-    shadow::SHADOW_UNRELATED,
-    single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES,
-    single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS,
-    size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT,
-    slow_vector_initialization::SLOW_VECTOR_INITIALIZATION,
-    std_instead_of_core::ALLOC_INSTEAD_OF_CORE,
-    std_instead_of_core::STD_INSTEAD_OF_ALLOC,
-    std_instead_of_core::STD_INSTEAD_OF_CORE,
-    strings::STRING_ADD,
-    strings::STRING_ADD_ASSIGN,
-    strings::STRING_FROM_UTF8_AS_BYTES,
-    strings::STRING_LIT_AS_BYTES,
-    strings::STRING_SLICE,
-    strings::STRING_TO_STRING,
-    strings::STR_TO_STRING,
-    strings::TRIM_SPLIT_WHITESPACE,
-    strlen_on_c_strings::STRLEN_ON_C_STRINGS,
-    suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS,
-    suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL,
-    suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL,
-    swap::ALMOST_SWAPPED,
-    swap::MANUAL_SWAP,
-    swap_ptr_to_ref::SWAP_PTR_TO_REF,
-    tabs_in_doc_comments::TABS_IN_DOC_COMMENTS,
-    temporary_assignment::TEMPORARY_ASSIGNMENT,
-    to_digit_is_some::TO_DIGIT_IS_SOME,
-    trailing_empty_array::TRAILING_EMPTY_ARRAY,
-    trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS,
-    trait_bounds::TYPE_REPETITION_IN_BOUNDS,
-    transmute::CROSSPOINTER_TRANSMUTE,
-    transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
-    transmute::TRANSMUTE_BYTES_TO_STR,
-    transmute::TRANSMUTE_FLOAT_TO_INT,
-    transmute::TRANSMUTE_INT_TO_BOOL,
-    transmute::TRANSMUTE_INT_TO_CHAR,
-    transmute::TRANSMUTE_INT_TO_FLOAT,
-    transmute::TRANSMUTE_NUM_TO_BYTES,
-    transmute::TRANSMUTE_PTR_TO_PTR,
-    transmute::TRANSMUTE_PTR_TO_REF,
-    transmute::TRANSMUTE_UNDEFINED_REPR,
-    transmute::TRANSMUTING_NULL,
-    transmute::UNSOUND_COLLECTION_TRANSMUTE,
-    transmute::USELESS_TRANSMUTE,
-    transmute::WRONG_TRANSMUTE,
-    types::BORROWED_BOX,
-    types::BOX_COLLECTION,
-    types::LINKEDLIST,
-    types::OPTION_OPTION,
-    types::RC_BUFFER,
-    types::RC_MUTEX,
-    types::REDUNDANT_ALLOCATION,
-    types::TYPE_COMPLEXITY,
-    types::VEC_BOX,
-    undocumented_unsafe_blocks::UNDOCUMENTED_UNSAFE_BLOCKS,
-    unicode::INVISIBLE_CHARACTERS,
-    unicode::NON_ASCII_LITERAL,
-    unicode::UNICODE_NOT_NFC,
-    uninit_vec::UNINIT_VEC,
-    unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD,
-    unit_types::LET_UNIT_VALUE,
-    unit_types::UNIT_ARG,
-    unit_types::UNIT_CMP,
-    unnamed_address::FN_ADDRESS_COMPARISONS,
-    unnamed_address::VTABLE_ADDRESS_COMPARISONS,
-    unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS,
-    unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS,
-    unnecessary_wraps::UNNECESSARY_WRAPS,
-    unnested_or_patterns::UNNESTED_OR_PATTERNS,
-    unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
-    unused_async::UNUSED_ASYNC,
-    unused_io_amount::UNUSED_IO_AMOUNT,
-    unused_peekable::UNUSED_PEEKABLE,
-    unused_rounding::UNUSED_ROUNDING,
-    unused_self::UNUSED_SELF,
-    unused_unit::UNUSED_UNIT,
-    unwrap::PANICKING_UNWRAP,
-    unwrap::UNNECESSARY_UNWRAP,
-    unwrap_in_result::UNWRAP_IN_RESULT,
-    upper_case_acronyms::UPPER_CASE_ACRONYMS,
-    use_self::USE_SELF,
-    useless_conversion::USELESS_CONVERSION,
-    vec::USELESS_VEC,
-    vec_init_then_push::VEC_INIT_THEN_PUSH,
-    wildcard_imports::ENUM_GLOB_USE,
-    wildcard_imports::WILDCARD_IMPORTS,
-    write::PRINTLN_EMPTY_STRING,
-    write::PRINT_LITERAL,
-    write::PRINT_STDERR,
-    write::PRINT_STDOUT,
-    write::PRINT_WITH_NEWLINE,
-    write::USE_DEBUG,
-    write::WRITELN_EMPTY_STRING,
-    write::WRITE_LITERAL,
-    write::WRITE_WITH_NEWLINE,
-    zero_div_zero::ZERO_DIVIDED_BY_ZERO,
-    zero_sized_map_values::ZERO_SIZED_MAP_VALUES,
-])
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs
deleted file mode 100644
index 65616d28d8f..00000000000
--- a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-// This file was generated by `cargo dev update_lints`.
-// Use that command to update this file and do not edit by hand.
-// Manual edits will be overwritten.
-
-store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
-    LintId::of(attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
-    LintId::of(casts::AS_PTR_CAST_MUT),
-    LintId::of(cognitive_complexity::COGNITIVE_COMPLEXITY),
-    LintId::of(copies::BRANCHES_SHARING_CODE),
-    LintId::of(derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ),
-    LintId::of(equatable_if_let::EQUATABLE_IF_LET),
-    LintId::of(fallible_impl_from::FALLIBLE_IMPL_FROM),
-    LintId::of(floating_point_arithmetic::IMPRECISE_FLOPS),
-    LintId::of(floating_point_arithmetic::SUBOPTIMAL_FLOPS),
-    LintId::of(future_not_send::FUTURE_NOT_SEND),
-    LintId::of(index_refutable_slice::INDEX_REFUTABLE_SLICE),
-    LintId::of(let_if_seq::USELESS_LET_IF_SEQ),
-    LintId::of(matches::SIGNIFICANT_DROP_IN_SCRUTINEE),
-    LintId::of(methods::ITER_ON_EMPTY_COLLECTIONS),
-    LintId::of(methods::ITER_ON_SINGLE_ITEMS),
-    LintId::of(methods::ITER_WITH_DRAIN),
-    LintId::of(methods::PATH_BUF_PUSH_OVERWRITE),
-    LintId::of(missing_const_for_fn::MISSING_CONST_FOR_FN),
-    LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
-    LintId::of(mutex_atomic::MUTEX_ATOMIC),
-    LintId::of(mutex_atomic::MUTEX_INTEGER),
-    LintId::of(non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY),
-    LintId::of(nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES),
-    LintId::of(option_if_let_else::OPTION_IF_LET_ELSE),
-    LintId::of(redundant_pub_crate::REDUNDANT_PUB_CRATE),
-    LintId::of(regex::TRIVIAL_REGEX),
-    LintId::of(strings::STRING_LIT_AS_BYTES),
-    LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
-    LintId::of(trailing_empty_array::TRAILING_EMPTY_ARRAY),
-    LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR),
-    LintId::of(unused_peekable::UNUSED_PEEKABLE),
-    LintId::of(unused_rounding::UNUSED_ROUNDING),
-    LintId::of(use_self::USE_SELF),
-])
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs b/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs
deleted file mode 100644
index 44e969585b5..00000000000
--- a/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs
+++ /dev/null
@@ -1,104 +0,0 @@
-// This file was generated by `cargo dev update_lints`.
-// Use that command to update this file and do not edit by hand.
-// Manual edits will be overwritten.
-
-store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
-    LintId::of(attrs::INLINE_ALWAYS),
-    LintId::of(casts::BORROW_AS_PTR),
-    LintId::of(casts::CAST_LOSSLESS),
-    LintId::of(casts::CAST_POSSIBLE_TRUNCATION),
-    LintId::of(casts::CAST_POSSIBLE_WRAP),
-    LintId::of(casts::CAST_PRECISION_LOSS),
-    LintId::of(casts::CAST_PTR_ALIGNMENT),
-    LintId::of(casts::CAST_SIGN_LOSS),
-    LintId::of(casts::PTR_AS_PTR),
-    LintId::of(checked_conversions::CHECKED_CONVERSIONS),
-    LintId::of(copies::SAME_FUNCTIONS_IN_IF_CONDITION),
-    LintId::of(copy_iterator::COPY_ITERATOR),
-    LintId::of(default::DEFAULT_TRAIT_ACCESS),
-    LintId::of(dereference::EXPLICIT_DEREF_METHODS),
-    LintId::of(dereference::REF_BINDING_TO_REFERENCE),
-    LintId::of(derive::EXPL_IMPL_CLONE_ON_COPY),
-    LintId::of(derive::UNSAFE_DERIVE_DESERIALIZE),
-    LintId::of(doc::DOC_LINK_WITH_QUOTES),
-    LintId::of(doc::DOC_MARKDOWN),
-    LintId::of(doc::MISSING_ERRORS_DOC),
-    LintId::of(doc::MISSING_PANICS_DOC),
-    LintId::of(empty_enum::EMPTY_ENUM),
-    LintId::of(enum_variants::MODULE_NAME_REPETITIONS),
-    LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS),
-    LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS),
-    LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS),
-    LintId::of(format_args::UNINLINED_FORMAT_ARGS),
-    LintId::of(functions::MUST_USE_CANDIDATE),
-    LintId::of(functions::TOO_MANY_LINES),
-    LintId::of(if_not_else::IF_NOT_ELSE),
-    LintId::of(implicit_hasher::IMPLICIT_HASHER),
-    LintId::of(inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR),
-    LintId::of(infinite_iter::MAYBE_INFINITE_ITER),
-    LintId::of(invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS),
-    LintId::of(items_after_statements::ITEMS_AFTER_STATEMENTS),
-    LintId::of(iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR),
-    LintId::of(large_stack_arrays::LARGE_STACK_ARRAYS),
-    LintId::of(let_underscore::LET_UNDERSCORE_DROP),
-    LintId::of(literal_representation::LARGE_DIGIT_GROUPS),
-    LintId::of(literal_representation::UNREADABLE_LITERAL),
-    LintId::of(loops::EXPLICIT_INTO_ITER_LOOP),
-    LintId::of(loops::EXPLICIT_ITER_LOOP),
-    LintId::of(macro_use::MACRO_USE_IMPORTS),
-    LintId::of(manual_assert::MANUAL_ASSERT),
-    LintId::of(manual_instant_elapsed::MANUAL_INSTANT_ELAPSED),
-    LintId::of(manual_string_new::MANUAL_STRING_NEW),
-    LintId::of(matches::MATCH_BOOL),
-    LintId::of(matches::MATCH_ON_VEC_ITEMS),
-    LintId::of(matches::MATCH_SAME_ARMS),
-    LintId::of(matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS),
-    LintId::of(matches::MATCH_WILD_ERR_ARM),
-    LintId::of(matches::SINGLE_MATCH_ELSE),
-    LintId::of(methods::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS),
-    LintId::of(methods::CLONED_INSTEAD_OF_COPIED),
-    LintId::of(methods::FILTER_MAP_NEXT),
-    LintId::of(methods::FLAT_MAP_OPTION),
-    LintId::of(methods::FROM_ITER_INSTEAD_OF_COLLECT),
-    LintId::of(methods::IMPLICIT_CLONE),
-    LintId::of(methods::INEFFICIENT_TO_STRING),
-    LintId::of(methods::MANUAL_OK_OR),
-    LintId::of(methods::MAP_UNWRAP_OR),
-    LintId::of(methods::NAIVE_BYTECOUNT),
-    LintId::of(methods::STABLE_SORT_PRIMITIVE),
-    LintId::of(methods::UNNECESSARY_JOIN),
-    LintId::of(misc::USED_UNDERSCORE_BINDING),
-    LintId::of(mismatching_type_param_order::MISMATCHING_TYPE_PARAM_ORDER),
-    LintId::of(mut_mut::MUT_MUT),
-    LintId::of(needless_continue::NEEDLESS_CONTINUE),
-    LintId::of(needless_for_each::NEEDLESS_FOR_EACH),
-    LintId::of(needless_pass_by_value::NEEDLESS_PASS_BY_VALUE),
-    LintId::of(no_effect::NO_EFFECT_UNDERSCORE_BINDING),
-    LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES),
-    LintId::of(non_expressive_names::SIMILAR_NAMES),
-    LintId::of(operators::FLOAT_CMP),
-    LintId::of(operators::NEEDLESS_BITWISE_BOOL),
-    LintId::of(operators::VERBOSE_BIT_MASK),
-    LintId::of(pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE),
-    LintId::of(pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF),
-    LintId::of(ranges::RANGE_MINUS_ONE),
-    LintId::of(ranges::RANGE_PLUS_ONE),
-    LintId::of(redundant_else::REDUNDANT_ELSE),
-    LintId::of(ref_option_ref::REF_OPTION_REF),
-    LintId::of(return_self_not_must_use::RETURN_SELF_NOT_MUST_USE),
-    LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
-    LintId::of(strings::STRING_ADD_ASSIGN),
-    LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
-    LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
-    LintId::of(transmute::TRANSMUTE_PTR_TO_PTR),
-    LintId::of(types::LINKEDLIST),
-    LintId::of(types::OPTION_OPTION),
-    LintId::of(unicode::UNICODE_NOT_NFC),
-    LintId::of(unnecessary_wraps::UNNECESSARY_WRAPS),
-    LintId::of(unnested_or_patterns::UNNESTED_OR_PATTERNS),
-    LintId::of(unused_async::UNUSED_ASYNC),
-    LintId::of(unused_self::UNUSED_SELF),
-    LintId::of(wildcard_imports::ENUM_GLOB_USE),
-    LintId::of(wildcard_imports::WILDCARD_IMPORTS),
-    LintId::of(zero_sized_map_values::ZERO_SIZED_MAP_VALUES),
-])
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_perf.rs b/src/tools/clippy/clippy_lints/src/lib.register_perf.rs
deleted file mode 100644
index 8e927470e02..00000000000
--- a/src/tools/clippy/clippy_lints/src/lib.register_perf.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-// This file was generated by `cargo dev update_lints`.
-// Use that command to update this file and do not edit by hand.
-// Manual edits will be overwritten.
-
-store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![
-    LintId::of(box_default::BOX_DEFAULT),
-    LintId::of(entry::MAP_ENTRY),
-    LintId::of(escape::BOXED_LOCAL),
-    LintId::of(format_args::FORMAT_IN_FORMAT_ARGS),
-    LintId::of(format_args::TO_STRING_IN_FORMAT_ARGS),
-    LintId::of(functions::RESULT_LARGE_ERR),
-    LintId::of(large_const_arrays::LARGE_CONST_ARRAYS),
-    LintId::of(large_enum_variant::LARGE_ENUM_VARIANT),
-    LintId::of(loops::MANUAL_MEMCPY),
-    LintId::of(loops::MISSING_SPIN_LOOP),
-    LintId::of(loops::NEEDLESS_COLLECT),
-    LintId::of(manual_retain::MANUAL_RETAIN),
-    LintId::of(methods::COLLAPSIBLE_STR_REPLACE),
-    LintId::of(methods::EXPECT_FUN_CALL),
-    LintId::of(methods::EXTEND_WITH_DRAIN),
-    LintId::of(methods::ITER_NTH),
-    LintId::of(methods::ITER_OVEREAGER_CLONED),
-    LintId::of(methods::MANUAL_STR_REPEAT),
-    LintId::of(methods::OR_FUN_CALL),
-    LintId::of(methods::SINGLE_CHAR_PATTERN),
-    LintId::of(methods::UNNECESSARY_TO_OWNED),
-    LintId::of(operators::CMP_OWNED),
-    LintId::of(redundant_clone::REDUNDANT_CLONE),
-    LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
-    LintId::of(types::BOX_COLLECTION),
-    LintId::of(types::REDUNDANT_ALLOCATION),
-    LintId::of(vec::USELESS_VEC),
-    LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH),
-])
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs
deleted file mode 100644
index f62d57af5b4..00000000000
--- a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs
+++ /dev/null
@@ -1,90 +0,0 @@
-// This file was generated by `cargo dev update_lints`.
-// Use that command to update this file and do not edit by hand.
-// Manual edits will be overwritten.
-
-store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
-    LintId::of(as_conversions::AS_CONVERSIONS),
-    LintId::of(asm_syntax::INLINE_ASM_X86_ATT_SYNTAX),
-    LintId::of(asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX),
-    LintId::of(assertions_on_result_states::ASSERTIONS_ON_RESULT_STATES),
-    LintId::of(attrs::ALLOW_ATTRIBUTES_WITHOUT_REASON),
-    LintId::of(casts::AS_UNDERSCORE),
-    LintId::of(casts::FN_TO_NUMERIC_CAST_ANY),
-    LintId::of(create_dir::CREATE_DIR),
-    LintId::of(dbg_macro::DBG_MACRO),
-    LintId::of(default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK),
-    LintId::of(default_union_representation::DEFAULT_UNION_REPRESENTATION),
-    LintId::of(disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS),
-    LintId::of(else_if_without_else::ELSE_IF_WITHOUT_ELSE),
-    LintId::of(empty_drop::EMPTY_DROP),
-    LintId::of(empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS),
-    LintId::of(exhaustive_items::EXHAUSTIVE_ENUMS),
-    LintId::of(exhaustive_items::EXHAUSTIVE_STRUCTS),
-    LintId::of(exit::EXIT),
-    LintId::of(float_literal::LOSSY_FLOAT_LITERAL),
-    LintId::of(format_push_string::FORMAT_PUSH_STRING),
-    LintId::of(if_then_some_else_none::IF_THEN_SOME_ELSE_NONE),
-    LintId::of(implicit_return::IMPLICIT_RETURN),
-    LintId::of(indexing_slicing::INDEXING_SLICING),
-    LintId::of(inherent_impl::MULTIPLE_INHERENT_IMPL),
-    LintId::of(large_include_file::LARGE_INCLUDE_FILE),
-    LintId::of(let_underscore::LET_UNDERSCORE_MUST_USE),
-    LintId::of(literal_representation::DECIMAL_LITERAL_REPRESENTATION),
-    LintId::of(matches::REST_PAT_IN_FULLY_BOUND_STRUCTS),
-    LintId::of(matches::TRY_ERR),
-    LintId::of(matches::WILDCARD_ENUM_MATCH_ARM),
-    LintId::of(mem_forget::MEM_FORGET),
-    LintId::of(methods::CLONE_ON_REF_PTR),
-    LintId::of(methods::EXPECT_USED),
-    LintId::of(methods::FILETYPE_IS_FILE),
-    LintId::of(methods::GET_UNWRAP),
-    LintId::of(methods::MAP_ERR_IGNORE),
-    LintId::of(methods::UNWRAP_USED),
-    LintId::of(methods::VERBOSE_FILE_READS),
-    LintId::of(misc_early::SEPARATED_LITERAL_SUFFIX),
-    LintId::of(misc_early::UNNEEDED_FIELD_PATTERN),
-    LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX),
-    LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),
-    LintId::of(missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES),
-    LintId::of(missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS),
-    LintId::of(missing_trait_methods::MISSING_TRAIT_METHODS),
-    LintId::of(mixed_read_write_in_expression::MIXED_READ_WRITE_IN_EXPRESSION),
-    LintId::of(module_style::MOD_MODULE_FILES),
-    LintId::of(module_style::SELF_NAMED_MODULE_FILES),
-    LintId::of(operators::ARITHMETIC_SIDE_EFFECTS),
-    LintId::of(operators::FLOAT_ARITHMETIC),
-    LintId::of(operators::FLOAT_CMP_CONST),
-    LintId::of(operators::INTEGER_ARITHMETIC),
-    LintId::of(operators::INTEGER_DIVISION),
-    LintId::of(operators::MODULO_ARITHMETIC),
-    LintId::of(panic_in_result_fn::PANIC_IN_RESULT_FN),
-    LintId::of(panic_unimplemented::PANIC),
-    LintId::of(panic_unimplemented::TODO),
-    LintId::of(panic_unimplemented::UNIMPLEMENTED),
-    LintId::of(panic_unimplemented::UNREACHABLE),
-    LintId::of(partial_pub_fields::PARTIAL_PUB_FIELDS),
-    LintId::of(pattern_type_mismatch::PATTERN_TYPE_MISMATCH),
-    LintId::of(pub_use::PUB_USE),
-    LintId::of(redundant_slicing::DEREF_BY_SLICING),
-    LintId::of(same_name_method::SAME_NAME_METHOD),
-    LintId::of(shadow::SHADOW_REUSE),
-    LintId::of(shadow::SHADOW_SAME),
-    LintId::of(shadow::SHADOW_UNRELATED),
-    LintId::of(single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES),
-    LintId::of(std_instead_of_core::ALLOC_INSTEAD_OF_CORE),
-    LintId::of(std_instead_of_core::STD_INSTEAD_OF_ALLOC),
-    LintId::of(std_instead_of_core::STD_INSTEAD_OF_CORE),
-    LintId::of(strings::STRING_ADD),
-    LintId::of(strings::STRING_SLICE),
-    LintId::of(strings::STRING_TO_STRING),
-    LintId::of(strings::STR_TO_STRING),
-    LintId::of(types::RC_BUFFER),
-    LintId::of(types::RC_MUTEX),
-    LintId::of(undocumented_unsafe_blocks::UNDOCUMENTED_UNSAFE_BLOCKS),
-    LintId::of(unicode::NON_ASCII_LITERAL),
-    LintId::of(unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS),
-    LintId::of(unwrap_in_result::UNWRAP_IN_RESULT),
-    LintId::of(write::PRINT_STDERR),
-    LintId::of(write::PRINT_STDOUT),
-    LintId::of(write::USE_DEBUG),
-])
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_style.rs b/src/tools/clippy/clippy_lints/src/lib.register_style.rs
deleted file mode 100644
index 3312f564855..00000000000
--- a/src/tools/clippy/clippy_lints/src/lib.register_style.rs
+++ /dev/null
@@ -1,131 +0,0 @@
-// This file was generated by `cargo dev update_lints`.
-// Use that command to update this file and do not edit by hand.
-// Manual edits will be overwritten.
-
-store.register_group(true, "clippy::style", Some("clippy_style"), vec![
-    LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
-    LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS),
-    LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON),
-    LintId::of(bool_to_int_with_if::BOOL_TO_INT_WITH_IF),
-    LintId::of(casts::FN_TO_NUMERIC_CAST),
-    LintId::of(casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION),
-    LintId::of(collapsible_if::COLLAPSIBLE_ELSE_IF),
-    LintId::of(collapsible_if::COLLAPSIBLE_IF),
-    LintId::of(comparison_chain::COMPARISON_CHAIN),
-    LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT),
-    LintId::of(default_instead_of_iter_empty::DEFAULT_INSTEAD_OF_ITER_EMPTY),
-    LintId::of(dereference::NEEDLESS_BORROW),
-    LintId::of(disallowed_macros::DISALLOWED_MACROS),
-    LintId::of(disallowed_methods::DISALLOWED_METHODS),
-    LintId::of(disallowed_names::DISALLOWED_NAMES),
-    LintId::of(disallowed_types::DISALLOWED_TYPES),
-    LintId::of(doc::MISSING_SAFETY_DOC),
-    LintId::of(doc::NEEDLESS_DOCTEST_MAIN),
-    LintId::of(enum_variants::ENUM_VARIANT_NAMES),
-    LintId::of(enum_variants::MODULE_INCEPTION),
-    LintId::of(eta_reduction::REDUNDANT_CLOSURE),
-    LintId::of(float_literal::EXCESSIVE_PRECISION),
-    LintId::of(from_over_into::FROM_OVER_INTO),
-    LintId::of(from_str_radix_10::FROM_STR_RADIX_10),
-    LintId::of(functions::DOUBLE_MUST_USE),
-    LintId::of(functions::MUST_USE_UNIT),
-    LintId::of(functions::RESULT_UNIT_ERR),
-    LintId::of(implicit_saturating_add::IMPLICIT_SATURATING_ADD),
-    LintId::of(implicit_saturating_sub::IMPLICIT_SATURATING_SUB),
-    LintId::of(inherent_to_string::INHERENT_TO_STRING),
-    LintId::of(init_numbered_fields::INIT_NUMBERED_FIELDS),
-    LintId::of(len_zero::COMPARISON_TO_EMPTY),
-    LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY),
-    LintId::of(len_zero::LEN_ZERO),
-    LintId::of(literal_representation::INCONSISTENT_DIGIT_GROUPING),
-    LintId::of(literal_representation::UNUSUAL_BYTE_GROUPINGS),
-    LintId::of(loops::FOR_KV_MAP),
-    LintId::of(loops::NEEDLESS_RANGE_LOOP),
-    LintId::of(loops::SAME_ITEM_PUSH),
-    LintId::of(loops::WHILE_LET_ON_ITERATOR),
-    LintId::of(main_recursion::MAIN_RECURSION),
-    LintId::of(manual_async_fn::MANUAL_ASYNC_FN),
-    LintId::of(manual_bits::MANUAL_BITS),
-    LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE),
-    LintId::of(match_result_ok::MATCH_RESULT_OK),
-    LintId::of(matches::COLLAPSIBLE_MATCH),
-    LintId::of(matches::INFALLIBLE_DESTRUCTURING_MATCH),
-    LintId::of(matches::MANUAL_MAP),
-    LintId::of(matches::MATCH_LIKE_MATCHES_MACRO),
-    LintId::of(matches::MATCH_OVERLAPPING_ARM),
-    LintId::of(matches::MATCH_REF_PATS),
-    LintId::of(matches::REDUNDANT_PATTERN_MATCHING),
-    LintId::of(matches::SINGLE_MATCH),
-    LintId::of(mem_replace::MEM_REPLACE_OPTION_WITH_NONE),
-    LintId::of(mem_replace::MEM_REPLACE_WITH_DEFAULT),
-    LintId::of(methods::BYTES_NTH),
-    LintId::of(methods::CHARS_LAST_CMP),
-    LintId::of(methods::CHARS_NEXT_CMP),
-    LintId::of(methods::ERR_EXPECT),
-    LintId::of(methods::GET_FIRST),
-    LintId::of(methods::INTO_ITER_ON_REF),
-    LintId::of(methods::IS_DIGIT_ASCII_RADIX),
-    LintId::of(methods::ITER_CLONED_COLLECT),
-    LintId::of(methods::ITER_NEXT_SLICE),
-    LintId::of(methods::ITER_NTH_ZERO),
-    LintId::of(methods::ITER_SKIP_NEXT),
-    LintId::of(methods::MANUAL_SATURATING_ARITHMETIC),
-    LintId::of(methods::MAP_CLONE),
-    LintId::of(methods::MAP_COLLECT_RESULT_UNIT),
-    LintId::of(methods::MUT_MUTEX_LOCK),
-    LintId::of(methods::NEW_RET_NO_SELF),
-    LintId::of(methods::OBFUSCATED_IF_ELSE),
-    LintId::of(methods::OK_EXPECT),
-    LintId::of(methods::OPTION_MAP_OR_NONE),
-    LintId::of(methods::RESULT_MAP_OR_INTO_OPTION),
-    LintId::of(methods::SHOULD_IMPLEMENT_TRAIT),
-    LintId::of(methods::SINGLE_CHAR_ADD_STR),
-    LintId::of(methods::STRING_EXTEND_CHARS),
-    LintId::of(methods::UNNECESSARY_FOLD),
-    LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS),
-    LintId::of(methods::UNWRAP_OR_ELSE_DEFAULT),
-    LintId::of(methods::WRONG_SELF_CONVENTION),
-    LintId::of(misc::TOPLEVEL_REF_ARG),
-    LintId::of(misc::ZERO_PTR),
-    LintId::of(misc_early::BUILTIN_TYPE_SHADOW),
-    LintId::of(misc_early::DOUBLE_NEG),
-    LintId::of(misc_early::DUPLICATE_UNDERSCORE_ARGUMENT),
-    LintId::of(misc_early::MIXED_CASE_HEX_LITERALS),
-    LintId::of(misc_early::REDUNDANT_PATTERN),
-    LintId::of(mut_reference::UNNECESSARY_MUT_PASSED),
-    LintId::of(needless_late_init::NEEDLESS_LATE_INIT),
-    LintId::of(needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS),
-    LintId::of(neg_multiply::NEG_MULTIPLY),
-    LintId::of(new_without_default::NEW_WITHOUT_DEFAULT),
-    LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
-    LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
-    LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
-    LintId::of(operators::ASSIGN_OP_PATTERN),
-    LintId::of(operators::OP_REF),
-    LintId::of(operators::PTR_EQ),
-    LintId::of(partialeq_to_none::PARTIALEQ_TO_NONE),
-    LintId::of(ptr::CMP_NULL),
-    LintId::of(ptr::PTR_ARG),
-    LintId::of(question_mark::QUESTION_MARK),
-    LintId::of(ranges::MANUAL_RANGE_CONTAINS),
-    LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES),
-    LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
-    LintId::of(returns::LET_AND_RETURN),
-    LintId::of(returns::NEEDLESS_RETURN),
-    LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS),
-    LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
-    LintId::of(strings::TRIM_SPLIT_WHITESPACE),
-    LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
-    LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME),
-    LintId::of(unit_types::LET_UNIT_VALUE),
-    LintId::of(unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS),
-    LintId::of(unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
-    LintId::of(unused_unit::UNUSED_UNIT),
-    LintId::of(upper_case_acronyms::UPPER_CASE_ACRONYMS),
-    LintId::of(write::PRINTLN_EMPTY_STRING),
-    LintId::of(write::PRINT_LITERAL),
-    LintId::of(write::PRINT_WITH_NEWLINE),
-    LintId::of(write::WRITELN_EMPTY_STRING),
-    LintId::of(write::WRITE_LITERAL),
-    LintId::of(write::WRITE_WITH_NEWLINE),
-])
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs b/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs
deleted file mode 100644
index b70c4bb73e5..00000000000
--- a/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-// This file was generated by `cargo dev update_lints`.
-// Use that command to update this file and do not edit by hand.
-// Manual edits will be overwritten.
-
-store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec![
-    LintId::of(almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE),
-    LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
-    LintId::of(await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE),
-    LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK),
-    LintId::of(await_holding_invalid::AWAIT_HOLDING_REFCELL_REF),
-    LintId::of(casts::CAST_ABS_TO_UNSIGNED),
-    LintId::of(casts::CAST_ENUM_CONSTRUCTOR),
-    LintId::of(casts::CAST_ENUM_TRUNCATION),
-    LintId::of(casts::CAST_NAN_TO_INT),
-    LintId::of(casts::CAST_SLICE_FROM_RAW_PARTS),
-    LintId::of(crate_in_macro_def::CRATE_IN_MACRO_DEF),
-    LintId::of(drop_forget_ref::DROP_NON_DROP),
-    LintId::of(drop_forget_ref::FORGET_NON_DROP),
-    LintId::of(duplicate_mod::DUPLICATE_MOD),
-    LintId::of(format_impl::PRINT_IN_FORMAT_IMPL),
-    LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
-    LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING),
-    LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
-    LintId::of(loops::EMPTY_LOOP),
-    LintId::of(loops::MUT_RANGE_BOUND),
-    LintId::of(methods::NO_EFFECT_REPLACE),
-    LintId::of(methods::SUSPICIOUS_MAP),
-    LintId::of(methods::SUSPICIOUS_TO_OWNED),
-    LintId::of(multi_assignments::MULTI_ASSIGNMENTS),
-    LintId::of(mut_key::MUTABLE_KEY_TYPE),
-    LintId::of(octal_escapes::OCTAL_ESCAPES),
-    LintId::of(operators::FLOAT_EQUALITY_WITHOUT_ABS),
-    LintId::of(operators::MISREFACTORED_ASSIGN_OP),
-    LintId::of(rc_clone_in_vec_init::RC_CLONE_IN_VEC_INIT),
-    LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
-    LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
-    LintId::of(swap_ptr_to_ref::SWAP_PTR_TO_REF),
-])
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 1307096b28d..601990cd6a3 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -26,14 +26,13 @@
 extern crate rustc_arena;
 extern crate rustc_ast;
 extern crate rustc_ast_pretty;
-extern crate rustc_attr;
 extern crate rustc_data_structures;
 extern crate rustc_driver;
 extern crate rustc_errors;
 extern crate rustc_hir;
 extern crate rustc_hir_analysis;
-extern crate rustc_hir_typeck;
 extern crate rustc_hir_pretty;
+extern crate rustc_hir_typeck;
 extern crate rustc_index;
 extern crate rustc_infer;
 extern crate rustc_lexer;
@@ -47,122 +46,24 @@ extern crate rustc_trait_selection;
 
 #[macro_use]
 extern crate clippy_utils;
+#[macro_use]
+extern crate declare_clippy_lint;
+
+use std::io;
+use std::path::PathBuf;
 
 use clippy_utils::parse_msrv;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_lint::LintId;
+use rustc_lint::{Lint, LintId};
 use rustc_semver::RustcVersion;
 use rustc_session::Session;
 
-/// Macro used to declare a Clippy lint.
-///
-/// Every lint declaration consists of 4 parts:
-///
-/// 1. The documentation, which is used for the website
-/// 2. The `LINT_NAME`. See [lint naming][lint_naming] on lint naming conventions.
-/// 3. The `lint_level`, which is a mapping from *one* of our lint groups to `Allow`, `Warn` or
-///    `Deny`. The lint level here has nothing to do with what lint groups the lint is a part of.
-/// 4. The `description` that contains a short explanation on what's wrong with code where the
-///    lint is triggered.
-///
-/// Currently the categories `style`, `correctness`, `suspicious`, `complexity` and `perf` are
-/// enabled by default. As said in the README.md of this repository, if the lint level mapping
-/// changes, please update README.md.
-///
-/// # Example
-///
-/// ```
-/// #![feature(rustc_private)]
-/// extern crate rustc_session;
-/// use rustc_session::declare_tool_lint;
-/// use clippy_lints::declare_clippy_lint;
-///
-/// declare_clippy_lint! {
-///     /// ### What it does
-///     /// Checks for ... (describe what the lint matches).
-///     ///
-///     /// ### Why is this bad?
-///     /// Supply the reason for linting the code.
-///     ///
-///     /// ### Example
-///     /// ```rust
-///     /// Insert a short example of code that triggers the lint
-///     /// ```
-///     ///
-///     /// Use instead:
-///     /// ```rust
-///     /// Insert a short example of improved code that doesn't trigger the lint
-///     /// ```
-///     pub LINT_NAME,
-///     pedantic,
-///     "description"
-/// }
-/// ```
-/// [lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
-#[macro_export]
-macro_rules! declare_clippy_lint {
-    { $(#[$attr:meta])* pub $name:tt, style, $description:tt } => {
-        declare_tool_lint! {
-            $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
-        }
-    };
-    { $(#[$attr:meta])* pub $name:tt, correctness, $description:tt } => {
-        declare_tool_lint! {
-            $(#[$attr])* pub clippy::$name, Deny, $description, report_in_external_macro: true
-        }
-    };
-    { $(#[$attr:meta])* pub $name:tt, suspicious, $description:tt } => {
-        declare_tool_lint! {
-            $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
-        }
-    };
-    { $(#[$attr:meta])* pub $name:tt, complexity, $description:tt } => {
-        declare_tool_lint! {
-            $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
-        }
-    };
-    { $(#[$attr:meta])* pub $name:tt, perf, $description:tt } => {
-        declare_tool_lint! {
-            $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
-        }
-    };
-    { $(#[$attr:meta])* pub $name:tt, pedantic, $description:tt } => {
-        declare_tool_lint! {
-            $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
-        }
-    };
-    { $(#[$attr:meta])* pub $name:tt, restriction, $description:tt } => {
-        declare_tool_lint! {
-            $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
-        }
-    };
-    { $(#[$attr:meta])* pub $name:tt, cargo, $description:tt } => {
-        declare_tool_lint! {
-            $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
-        }
-    };
-    { $(#[$attr:meta])* pub $name:tt, nursery, $description:tt } => {
-        declare_tool_lint! {
-            $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
-        }
-    };
-    { $(#[$attr:meta])* pub $name:tt, internal, $description:tt } => {
-        declare_tool_lint! {
-            $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
-        }
-    };
-    { $(#[$attr:meta])* pub $name:tt, internal_warn, $description:tt } => {
-        declare_tool_lint! {
-            $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
-        }
-    };
-}
-
 #[cfg(feature = "internal")]
 pub mod deprecated_lints;
 #[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))]
 mod utils;
 
+mod declared_lints;
 mod renamed_lints;
 
 // begin lints modules, do not remove this comment, it’s used in `update_lints`
@@ -231,6 +132,7 @@ mod format_impl;
 mod format_push_string;
 mod formatting;
 mod from_over_into;
+mod from_raw_with_void_ptr;
 mod from_str_radix_10;
 mod functions;
 mod future_not_send;
@@ -249,6 +151,7 @@ mod inherent_impl;
 mod inherent_to_string;
 mod init_numbered_fields;
 mod inline_fn_without_body;
+mod instant_subtraction;
 mod int_plus_one;
 mod invalid_upcast_comparisons;
 mod invalid_utf8_in_unchecked;
@@ -270,7 +173,8 @@ mod manual_assert;
 mod manual_async_fn;
 mod manual_bits;
 mod manual_clamp;
-mod manual_instant_elapsed;
+mod manual_is_ascii_check;
+mod manual_let_else;
 mod manual_non_exhaustive;
 mod manual_rem_euclid;
 mod manual_retain;
@@ -365,6 +269,7 @@ mod strings;
 mod strlen_on_c_strings;
 mod suspicious_operation_groupings;
 mod suspicious_trait_impl;
+mod suspicious_xor_used_as_pow;
 mod swap;
 mod swap_ptr_to_ref;
 mod tabs_in_doc_comments;
@@ -404,8 +309,8 @@ mod zero_div_zero;
 mod zero_sized_map_values;
 // end lints modules, do not remove this comment, it’s used in `update_lints`
 
-pub use crate::utils::conf::Conf;
 use crate::utils::conf::{format_error, TryConf};
+pub use crate::utils::conf::{lookup_conf_file, Conf};
 
 /// Register all pre expansion lints
 ///
@@ -462,8 +367,8 @@ fn read_msrv(conf: &Conf, sess: &Session) -> Option<RustcVersion> {
 }
 
 #[doc(hidden)]
-pub fn read_conf(sess: &Session) -> Conf {
-    let file_name = match utils::conf::lookup_conf_file() {
+pub fn read_conf(sess: &Session, path: &io::Result<Option<PathBuf>>) -> Conf {
+    let file_name = match path {
         Ok(Some(path)) => path,
         Ok(None) => return Conf::default(),
         Err(error) => {
@@ -473,7 +378,7 @@ pub fn read_conf(sess: &Session) -> Conf {
         },
     };
 
-    let TryConf { conf, errors, warnings } = utils::conf::read(&file_name);
+    let TryConf { conf, errors, warnings } = utils::conf::read(file_name);
     // all conf errors are non-fatal, we just use the default conf in case of error
     for error in errors {
         sess.err(format!(
@@ -495,31 +400,121 @@ pub fn read_conf(sess: &Session) -> Conf {
     conf
 }
 
+#[derive(Default)]
+struct RegistrationGroups {
+    all: Vec<LintId>,
+    cargo: Vec<LintId>,
+    complexity: Vec<LintId>,
+    correctness: Vec<LintId>,
+    nursery: Vec<LintId>,
+    pedantic: Vec<LintId>,
+    perf: Vec<LintId>,
+    restriction: Vec<LintId>,
+    style: Vec<LintId>,
+    suspicious: Vec<LintId>,
+    #[cfg(feature = "internal")]
+    internal: Vec<LintId>,
+}
+
+impl RegistrationGroups {
+    #[rustfmt::skip]
+    fn register(self, store: &mut rustc_lint::LintStore) {
+        store.register_group(true, "clippy::all", Some("clippy_all"), self.all);
+        store.register_group(true, "clippy::cargo", Some("clippy_cargo"), self.cargo);
+        store.register_group(true, "clippy::complexity", Some("clippy_complexity"), self.complexity);
+        store.register_group(true, "clippy::correctness", Some("clippy_correctness"), self.correctness);
+        store.register_group(true, "clippy::nursery", Some("clippy_nursery"), self.nursery);
+        store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), self.pedantic);
+        store.register_group(true, "clippy::perf", Some("clippy_perf"), self.perf);
+        store.register_group(true, "clippy::restriction", Some("clippy_restriction"), self.restriction);
+        store.register_group(true, "clippy::style", Some("clippy_style"), self.style);
+        store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), self.suspicious);
+        #[cfg(feature = "internal")]
+        store.register_group(true, "clippy::internal", Some("clippy_internal"), self.internal);
+    }
+}
+
+#[derive(Copy, Clone)]
+pub(crate) enum LintCategory {
+    Cargo,
+    Complexity,
+    Correctness,
+    Nursery,
+    Pedantic,
+    Perf,
+    Restriction,
+    Style,
+    Suspicious,
+    #[cfg(feature = "internal")]
+    Internal,
+}
+#[allow(clippy::enum_glob_use)]
+use LintCategory::*;
+
+impl LintCategory {
+    fn is_all(self) -> bool {
+        matches!(self, Correctness | Suspicious | Style | Complexity | Perf)
+    }
+
+    fn group(self, groups: &mut RegistrationGroups) -> &mut Vec<LintId> {
+        match self {
+            Cargo => &mut groups.cargo,
+            Complexity => &mut groups.complexity,
+            Correctness => &mut groups.correctness,
+            Nursery => &mut groups.nursery,
+            Pedantic => &mut groups.pedantic,
+            Perf => &mut groups.perf,
+            Restriction => &mut groups.restriction,
+            Style => &mut groups.style,
+            Suspicious => &mut groups.suspicious,
+            #[cfg(feature = "internal")]
+            Internal => &mut groups.internal,
+        }
+    }
+}
+
+pub(crate) struct LintInfo {
+    /// Double reference to maintain pointer equality
+    lint: &'static &'static Lint,
+    category: LintCategory,
+    explanation: &'static str,
+}
+
+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),
+        None => println!("unknown lint: {name}"),
+    }
+}
+
+fn register_categories(store: &mut rustc_lint::LintStore) {
+    let mut groups = RegistrationGroups::default();
+
+    for LintInfo { lint, category, .. } in declared_lints::LINTS {
+        if category.is_all() {
+            groups.all.push(LintId::of(lint));
+        }
+
+        category.group(&mut groups).push(LintId::of(lint));
+    }
+
+    let lints: Vec<&'static Lint> = declared_lints::LINTS.iter().map(|info| *info.lint).collect();
+
+    store.register_lints(&lints);
+    groups.register(store);
+}
+
 /// Register all lints and lint groups with the rustc plugin registry
 ///
 /// Used in `./src/driver.rs`.
 #[expect(clippy::too_many_lines)]
 pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) {
     register_removed_non_tool_lints(store);
+    register_categories(store);
 
     include!("lib.deprecated.rs");
 
-    include!("lib.register_lints.rs");
-    include!("lib.register_restriction.rs");
-    include!("lib.register_pedantic.rs");
-
-    #[cfg(feature = "internal")]
-    include!("lib.register_internal.rs");
-
-    include!("lib.register_all.rs");
-    include!("lib.register_style.rs");
-    include!("lib.register_complexity.rs");
-    include!("lib.register_correctness.rs");
-    include!("lib.register_suspicious.rs");
-    include!("lib.register_perf.rs");
-    include!("lib.register_cargo.rs");
-    include!("lib.register_nursery.rs");
-
     #[cfg(feature = "internal")]
     {
         if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) {
@@ -614,6 +609,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         ))
     });
     store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv)));
+    let matches_for_let_else = conf.matches_for_let_else;
+    store.register_late_pass(move |_| Box::new(manual_let_else::ManualLetElse::new(msrv, matches_for_let_else)));
     store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv)));
     store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv)));
     store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv)));
@@ -735,7 +732,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     let max_trait_bounds = conf.max_trait_bounds;
     store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds)));
     store.register_late_pass(|_| Box::new(comparison_chain::ComparisonChain));
-    store.register_late_pass(|_| Box::new(mut_key::MutableKeyType));
+    let ignore_interior_mutability = conf.ignore_interior_mutability.clone();
+    store.register_late_pass(move |_| Box::new(mut_key::MutableKeyType::new(ignore_interior_mutability.clone())));
     store.register_early_pass(|| Box::new(reference::DerefAddrOf));
     store.register_early_pass(|| Box::new(double_parens::DoubleParens));
     store.register_late_pass(|_| Box::new(format_impl::FormatImpl::new()));
@@ -794,10 +792,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic));
     store.register_early_pass(|| Box::new(as_conversions::AsConversions));
     store.register_late_pass(|_| Box::new(let_underscore::LetUnderscore));
-    store.register_early_pass(|| Box::new(single_component_path_imports::SingleComponentPathImports));
+    store.register_early_pass(|| Box::<single_component_path_imports::SingleComponentPathImports>::default());
     let max_fn_params_bools = conf.max_fn_params_bools;
     let max_struct_bools = conf.max_struct_bools;
-    store.register_early_pass(move || {
+    store.register_late_pass(move |_| {
         Box::new(excessive_bools::ExcessiveBools::new(
             max_struct_bools,
             max_fn_params_bools,
@@ -879,13 +877,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::<only_used_in_recursion::OnlyUsedInRecursion>::default());
     let allow_dbg_in_tests = conf.allow_dbg_in_tests;
     store.register_late_pass(move |_| Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests)));
+    let allow_print_in_tests = conf.allow_print_in_tests;
+    store.register_late_pass(move |_| Box::new(write::Write::new(allow_print_in_tests)));
     let cargo_ignore_publish = conf.cargo_ignore_publish;
     store.register_late_pass(move |_| {
         Box::new(cargo::Cargo {
             ignore_publish: cargo_ignore_publish,
         })
     });
-    store.register_late_pass(|_| Box::<write::Write>::default());
     store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef));
     store.register_early_pass(|| Box::new(empty_structs_with_brackets::EmptyStructsWithBrackets));
     store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings));
@@ -908,7 +907,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
     store.register_late_pass(|_| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
     store.register_late_pass(|_| Box::<std_instead_of_core::StdReexports>::default());
-    store.register_late_pass(|_| Box::new(manual_instant_elapsed::ManualInstantElapsed));
+    store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv)));
     store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone));
     store.register_late_pass(move |_| Box::new(manual_clamp::ManualClamp::new(msrv)));
     store.register_late_pass(|_| Box::new(manual_string_new::ManualStringNew));
@@ -919,6 +918,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(implicit_saturating_add::ImplicitSaturatingAdd));
     store.register_early_pass(|| Box::new(partial_pub_fields::PartialPubFields));
     store.register_late_pass(|_| Box::new(missing_trait_methods::MissingTraitMethods));
+    store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr));
+    store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow));
+    store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv)));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 54c316358a1..0bb9eca1528 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint;
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::trait_ref_of_method;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter};
@@ -152,6 +152,7 @@ fn check_fn_inner<'tcx>(
         .params
         .iter()
         .filter(|param| matches!(param.kind, GenericParamKind::Type { .. }));
+
     for typ in types {
         for pred in generics.bounds_for_param(cx.tcx.hir().local_def_id(typ.hir_id)) {
             if pred.origin == PredicateOrigin::WhereClause {
@@ -188,15 +189,30 @@ fn check_fn_inner<'tcx>(
             }
         }
     }
-    if could_use_elision(cx, decl, body, trait_sig, generics.params) {
-        span_lint(
+
+    if let Some(elidable_lts) = could_use_elision(cx, decl, body, trait_sig, generics.params) {
+        let lts = elidable_lts
+            .iter()
+            // In principle, the result of the call to `Node::ident` could be `unwrap`ped, as `DefId` should refer to a
+            // `Node::GenericParam`.
+            .filter_map(|&(def_id, _)| cx.tcx.hir().get_by_def_id(def_id).ident())
+            .map(|ident| ident.to_string())
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        span_lint_and_then(
             cx,
             NEEDLESS_LIFETIMES,
             span.with_hi(decl.output.span().hi()),
-            "explicit lifetimes given in parameter types where they could be elided \
-             (or replaced with `'_` if needed by type declaration)",
+            &format!("the following explicit lifetimes could be elided: {lts}"),
+            |diag| {
+                if let Some(span) = elidable_lts.iter().find_map(|&(_, span)| span) {
+                    diag.span_help(span, "replace with `'_` in generic arguments such as here");
+                }
+            },
         );
     }
+
     if report_extra_lifetimes {
         self::report_extra_lifetimes(cx, decl, generics);
     }
@@ -227,7 +243,7 @@ fn could_use_elision<'tcx>(
     body: Option<BodyId>,
     trait_sig: Option<&[Ident]>,
     named_generics: &'tcx [GenericParam<'_>],
-) -> bool {
+) -> Option<Vec<(LocalDefId, Option<Span>)>> {
     // There are two scenarios where elision works:
     // * no output references, all input references have different LT
     // * output references, exactly one input reference with same LT
@@ -254,7 +270,7 @@ fn could_use_elision<'tcx>(
     }
 
     if input_visitor.abort() || output_visitor.abort() {
-        return false;
+        return None;
     }
 
     let input_lts = input_visitor.lts;
@@ -262,7 +278,7 @@ fn could_use_elision<'tcx>(
 
     if let Some(trait_sig) = trait_sig {
         if explicit_self_type(cx, func, trait_sig.first().copied()) {
-            return false;
+            return None;
         }
     }
 
@@ -271,7 +287,7 @@ fn could_use_elision<'tcx>(
 
         let first_ident = body.params.first().and_then(|param| param.pat.simple_ident());
         if explicit_self_type(cx, func, first_ident) {
-            return false;
+            return None;
         }
 
         let mut checker = BodyLifetimeChecker {
@@ -279,14 +295,14 @@ fn could_use_elision<'tcx>(
         };
         checker.visit_expr(body.value);
         if checker.lifetimes_used_in_body {
-            return false;
+            return None;
         }
     }
 
     // check for lifetimes from higher scopes
     for lt in input_lts.iter().chain(output_lts.iter()) {
         if !allowed_lts.contains(lt) {
-            return false;
+            return None;
         }
     }
 
@@ -302,48 +318,45 @@ fn could_use_elision<'tcx>(
         for lt in input_visitor.nested_elision_site_lts {
             if let RefLt::Named(def_id) = lt {
                 if allowed_lts.contains(&cx.tcx.item_name(def_id.to_def_id())) {
-                    return false;
+                    return None;
                 }
             }
         }
         for lt in output_visitor.nested_elision_site_lts {
             if let RefLt::Named(def_id) = lt {
                 if allowed_lts.contains(&cx.tcx.item_name(def_id.to_def_id())) {
-                    return false;
+                    return None;
                 }
             }
         }
     }
 
-    // no input lifetimes? easy case!
-    if input_lts.is_empty() {
-        false
-    } else if output_lts.is_empty() {
-        // no output lifetimes, check distinctness of input lifetimes
+    // A lifetime can be newly elided if:
+    // - It occurs only once among the inputs.
+    // - If there are multiple input lifetimes, then the newly elided lifetime does not occur among the
+    //   outputs (because eliding such an lifetime would create an ambiguity).
+    let elidable_lts = named_lifetime_occurrences(&input_lts)
+        .into_iter()
+        .filter_map(|(def_id, occurrences)| {
+            if occurrences == 1 && (input_lts.len() == 1 || !output_lts.contains(&RefLt::Named(def_id))) {
+                Some((
+                    def_id,
+                    input_visitor
+                        .lifetime_generic_arg_spans
+                        .get(&def_id)
+                        .or_else(|| output_visitor.lifetime_generic_arg_spans.get(&def_id))
+                        .copied(),
+                ))
+            } else {
+                None
+            }
+        })
+        .collect::<Vec<_>>();
 
-        // only unnamed and static, ok
-        let unnamed_and_static = input_lts.iter().all(|lt| *lt == RefLt::Unnamed || *lt == RefLt::Static);
-        if unnamed_and_static {
-            return false;
-        }
-        // we have no output reference, so we only need all distinct lifetimes
-        input_lts.len() == unique_lifetimes(&input_lts)
+    if elidable_lts.is_empty() {
+        None
     } else {
-        // we have output references, so we need one input reference,
-        // and all output lifetimes must be the same
-        if unique_lifetimes(&output_lts) > 1 {
-            return false;
-        }
-        if input_lts.len() == 1 {
-            match (&input_lts[0], &output_lts[0]) {
-                (&RefLt::Named(n1), &RefLt::Named(n2)) if n1 == n2 => true,
-                (&RefLt::Named(_), &RefLt::Unnamed) => true,
-                _ => false, /* already elided, different named lifetimes
-                             * or something static going on */
-            }
-        } else {
-            false
-        }
+        Some(elidable_lts)
     }
 }
 
@@ -359,16 +372,31 @@ fn allowed_lts_from(tcx: TyCtxt<'_>, named_generics: &[GenericParam<'_>]) -> FxH
     allowed_lts
 }
 
-/// Number of unique lifetimes in the given vector.
+/// Number of times each named lifetime occurs in the given slice. Returns a vector to preserve
+/// relative order.
 #[must_use]
-fn unique_lifetimes(lts: &[RefLt]) -> usize {
-    lts.iter().collect::<FxHashSet<_>>().len()
+fn named_lifetime_occurrences(lts: &[RefLt]) -> Vec<(LocalDefId, usize)> {
+    let mut occurrences = Vec::new();
+    for lt in lts {
+        if let &RefLt::Named(curr_def_id) = lt {
+            if let Some(pair) = occurrences
+                .iter_mut()
+                .find(|(prev_def_id, _)| *prev_def_id == curr_def_id)
+            {
+                pair.1 += 1;
+            } else {
+                occurrences.push((curr_def_id, 1));
+            }
+        }
+    }
+    occurrences
 }
 
 /// A visitor usable for `rustc_front::visit::walk_ty()`.
 struct RefVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
     lts: Vec<RefLt>,
+    lifetime_generic_arg_spans: FxHashMap<LocalDefId, Span>,
     nested_elision_site_lts: Vec<RefLt>,
     unelided_trait_object_lifetime: bool,
 }
@@ -378,6 +406,7 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
         Self {
             cx,
             lts: Vec::new(),
+            lifetime_generic_arg_spans: FxHashMap::default(),
             nested_elision_site_lts: Vec::new(),
             unelided_trait_object_lifetime: false,
         }
@@ -467,6 +496,22 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
             _ => walk_ty(self, ty),
         }
     }
+
+    fn visit_generic_arg(&mut self, generic_arg: &'tcx GenericArg<'tcx>) {
+        if let GenericArg::Lifetime(l) = generic_arg
+            && let LifetimeName::Param(def_id, _) = l.name
+        {
+            self.lifetime_generic_arg_spans.entry(def_id).or_insert(l.span);
+        }
+        // Replace with `walk_generic_arg` if/when https://github.com/rust-lang/rust/pull/103692 lands.
+        // walk_generic_arg(self, generic_arg);
+        match generic_arg {
+            GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
+            GenericArg::Type(ty) => self.visit_ty(ty),
+            GenericArg::Const(ct) => self.visit_anon_const(&ct.value),
+            GenericArg::Infer(inf) => self.visit_infer(inf),
+        }
+    }
 }
 
 /// Are any lifetimes mentioned in the `where` clause? If so, we don't try to
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index bcf278d9c83..8e52cac4323 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -9,7 +9,6 @@ mod manual_flatten;
 mod manual_memcpy;
 mod missing_spin_loop;
 mod mut_range_bound;
-mod needless_collect;
 mod needless_range_loop;
 mod never_loop;
 mod same_item_push;
@@ -207,28 +206,6 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for functions collecting an iterator when collect
-    /// is not needed.
-    ///
-    /// ### Why is this bad?
-    /// `collect` causes the allocation of a new data structure,
-    /// when this allocation may not be needed.
-    ///
-    /// ### Example
-    /// ```rust
-    /// # let iterator = vec![1].into_iter();
-    /// let len = iterator.clone().collect::<Vec<_>>().len();
-    /// // should be
-    /// let len = iterator.count();
-    /// ```
-    #[clippy::version = "1.30.0"]
-    pub NEEDLESS_COLLECT,
-    perf,
-    "collecting an iterator when collect is not needed"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
     /// Checks `for` loops over slices with an explicit counter
     /// and suggests the use of `.enumerate()`.
     ///
@@ -605,7 +582,6 @@ declare_lint_pass!(Loops => [
     EXPLICIT_INTO_ITER_LOOP,
     ITER_NEXT_LOOP,
     WHILE_LET_LOOP,
-    NEEDLESS_COLLECT,
     EXPLICIT_COUNTER_LOOP,
     EMPTY_LOOP,
     WHILE_LET_ON_ITERATOR,
@@ -667,8 +643,6 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
             while_immutable_condition::check(cx, condition, body);
             missing_spin_loop::check(cx, condition, body);
         }
-
-        needless_collect::check(expr, cx);
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
index 91b321c4474..4dae93f6028 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
@@ -52,8 +52,8 @@ fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option<HirId>
     None
 }
 
-fn check_for_mutation<'tcx>(
-    cx: &LateContext<'tcx>,
+fn check_for_mutation(
+    cx: &LateContext<'_>,
     body: &Expr<'_>,
     bound_id_start: Option<HirId>,
     bound_id_end: Option<HirId>,
@@ -113,13 +113,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
         }
     }
 
-    fn fake_read(
-        &mut self,
-        _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>,
-        _: FakeReadCause,
-        _: HirId,
-    ) {
-    }
+    fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
 }
 
 impl MutatePairDelegate<'_, '_> {
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index 16b00ad6637..14f161f5102 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -4,7 +4,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::ForLoop;
 use clippy_utils::source::snippet;
 use rustc_errors::Applicability;
-use rustc_hir::{Block, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind};
+use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind};
 use rustc_lint::LateContext;
 use rustc_span::Span;
 use std::iter::{once, Iterator};
@@ -16,7 +16,7 @@ pub(super) fn check(
     span: Span,
     for_loop: Option<&ForLoop<'_>>,
 ) {
-    match never_loop_block(block, loop_id) {
+    match never_loop_block(block, &mut Vec::new(), loop_id) {
         NeverLoopResult::AlwaysBreak => {
             span_lint_and_then(cx, NEVER_LOOP, span, "this loop never actually loops", |diag| {
                 if let Some(ForLoop {
@@ -92,35 +92,34 @@ fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult
     }
 }
 
-fn never_loop_block(block: &Block<'_>, main_loop_id: HirId) -> NeverLoopResult {
-    let mut iter = block
+fn never_loop_block(block: &Block<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: HirId) -> NeverLoopResult {
+    let iter = block
         .stmts
         .iter()
         .filter_map(stmt_to_expr)
         .chain(block.expr.map(|expr| (expr, None)));
-    never_loop_expr_seq(&mut iter, main_loop_id)
-}
 
-fn never_loop_expr_seq<'a, T: Iterator<Item = (&'a Expr<'a>, Option<&'a Block<'a>>)>>(
-    es: &mut T,
-    main_loop_id: HirId,
-) -> NeverLoopResult {
-    es.map(|(e, els)| {
-        let e = never_loop_expr(e, main_loop_id);
-        els.map_or(e, |els| combine_branches(e, never_loop_block(els, main_loop_id)))
+    iter.map(|(e, els)| {
+        let e = never_loop_expr(e, ignore_ids, main_loop_id);
+        // els is an else block in a let...else binding
+        els.map_or(e, |els| {
+            combine_branches(e, never_loop_block(els, ignore_ids, main_loop_id))
+        })
     })
     .fold(NeverLoopResult::Otherwise, combine_seq)
 }
 
 fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<(&'tcx Expr<'tcx>, Option<&'tcx Block<'tcx>>)> {
     match stmt.kind {
-        StmtKind::Semi(e, ..) | StmtKind::Expr(e, ..) => Some((e, None)),
+        StmtKind::Semi(e) | StmtKind::Expr(e) => Some((e, None)),
+        // add the let...else expression (if present)
         StmtKind::Local(local) => local.init.map(|init| (init, local.els)),
         StmtKind::Item(..) => None,
     }
 }
 
-fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
+#[allow(clippy::too_many_lines)]
+fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: HirId) -> NeverLoopResult {
     match expr.kind {
         ExprKind::Box(e)
         | ExprKind::Unary(_, e)
@@ -129,47 +128,56 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
         | ExprKind::Field(e, _)
         | ExprKind::AddrOf(_, _, e)
         | ExprKind::Repeat(e, _)
-        | ExprKind::DropTemps(e) => never_loop_expr(e, main_loop_id),
-        ExprKind::Let(let_expr) => never_loop_expr(let_expr.init, main_loop_id),
-        ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(&mut es.iter(), main_loop_id),
-        ExprKind::MethodCall(_, receiver, es, _) => {
-            never_loop_expr_all(&mut std::iter::once(receiver).chain(es.iter()), main_loop_id)
-        },
+        | ExprKind::DropTemps(e) => never_loop_expr(e, ignore_ids, main_loop_id),
+        ExprKind::Let(let_expr) => never_loop_expr(let_expr.init, ignore_ids, main_loop_id),
+        ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(&mut es.iter(), ignore_ids, main_loop_id),
+        ExprKind::MethodCall(_, receiver, es, _) => never_loop_expr_all(
+            &mut std::iter::once(receiver).chain(es.iter()),
+            ignore_ids,
+            main_loop_id,
+        ),
         ExprKind::Struct(_, fields, base) => {
-            let fields = never_loop_expr_all(&mut fields.iter().map(|f| f.expr), main_loop_id);
+            let fields = never_loop_expr_all(&mut fields.iter().map(|f| f.expr), ignore_ids, main_loop_id);
             if let Some(base) = base {
-                combine_both(fields, never_loop_expr(base, main_loop_id))
+                combine_both(fields, never_loop_expr(base, ignore_ids, main_loop_id))
             } else {
                 fields
             }
         },
-        ExprKind::Call(e, es) => never_loop_expr_all(&mut once(e).chain(es.iter()), main_loop_id),
+        ExprKind::Call(e, es) => never_loop_expr_all(&mut once(e).chain(es.iter()), ignore_ids, main_loop_id),
         ExprKind::Binary(_, e1, e2)
         | ExprKind::Assign(e1, e2, _)
         | ExprKind::AssignOp(_, e1, e2)
-        | ExprKind::Index(e1, e2) => never_loop_expr_all(&mut [e1, e2].iter().copied(), main_loop_id),
+        | ExprKind::Index(e1, e2) => never_loop_expr_all(&mut [e1, e2].iter().copied(), ignore_ids, main_loop_id),
         ExprKind::Loop(b, _, _, _) => {
             // Break can come from the inner loop so remove them.
-            absorb_break(never_loop_block(b, main_loop_id))
+            absorb_break(never_loop_block(b, ignore_ids, main_loop_id))
         },
         ExprKind::If(e, e2, e3) => {
-            let e1 = never_loop_expr(e, main_loop_id);
-            let e2 = never_loop_expr(e2, main_loop_id);
-            let e3 = e3
-                .as_ref()
-                .map_or(NeverLoopResult::Otherwise, |e| never_loop_expr(e, main_loop_id));
+            let e1 = never_loop_expr(e, ignore_ids, main_loop_id);
+            let e2 = never_loop_expr(e2, ignore_ids, main_loop_id);
+            let e3 = e3.as_ref().map_or(NeverLoopResult::Otherwise, |e| {
+                never_loop_expr(e, ignore_ids, main_loop_id)
+            });
             combine_seq(e1, combine_branches(e2, e3))
         },
         ExprKind::Match(e, arms, _) => {
-            let e = never_loop_expr(e, main_loop_id);
+            let e = never_loop_expr(e, ignore_ids, main_loop_id);
             if arms.is_empty() {
                 e
             } else {
-                let arms = never_loop_expr_branch(&mut arms.iter().map(|a| a.body), main_loop_id);
+                let arms = never_loop_expr_branch(&mut arms.iter().map(|a| a.body), ignore_ids, main_loop_id);
                 combine_seq(e, arms)
             }
         },
-        ExprKind::Block(b, _) => never_loop_block(b, main_loop_id),
+        ExprKind::Block(b, l) => {
+            if l.is_some() {
+                ignore_ids.push(b.hir_id);
+            }
+            let ret = never_loop_block(b, ignore_ids, main_loop_id);
+            ignore_ids.pop();
+            ret
+        },
         ExprKind::Continue(d) => {
             let id = d
                 .target_id
@@ -180,20 +188,32 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
                 NeverLoopResult::AlwaysBreak
             }
         },
+        // checks if break targets a block instead of a loop
+        ExprKind::Break(Destination { target_id: Ok(t), .. }, e) if ignore_ids.contains(&t) => e
+            .map_or(NeverLoopResult::Otherwise, |e| {
+                combine_seq(never_loop_expr(e, ignore_ids, main_loop_id), NeverLoopResult::Otherwise)
+            }),
         ExprKind::Break(_, e) | ExprKind::Ret(e) => e.as_ref().map_or(NeverLoopResult::AlwaysBreak, |e| {
-            combine_seq(never_loop_expr(e, main_loop_id), NeverLoopResult::AlwaysBreak)
+            combine_seq(
+                never_loop_expr(e, ignore_ids, main_loop_id),
+                NeverLoopResult::AlwaysBreak,
+            )
         }),
         ExprKind::InlineAsm(asm) => asm
             .operands
             .iter()
             .map(|(o, _)| match o {
                 InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
-                    never_loop_expr(expr, main_loop_id)
+                    never_loop_expr(expr, ignore_ids, main_loop_id)
                 },
-                InlineAsmOperand::Out { expr, .. } => never_loop_expr_all(&mut expr.iter().copied(), main_loop_id),
-                InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
-                    never_loop_expr_all(&mut once(*in_expr).chain(out_expr.iter().copied()), main_loop_id)
+                InlineAsmOperand::Out { expr, .. } => {
+                    never_loop_expr_all(&mut expr.iter().copied(), ignore_ids, main_loop_id)
                 },
+                InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => never_loop_expr_all(
+                    &mut once(*in_expr).chain(out_expr.iter().copied()),
+                    ignore_ids,
+                    main_loop_id,
+                ),
                 InlineAsmOperand::Const { .. }
                 | InlineAsmOperand::SymFn { .. }
                 | InlineAsmOperand::SymStatic { .. } => NeverLoopResult::Otherwise,
@@ -208,13 +228,21 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
     }
 }
 
-fn never_loop_expr_all<'a, T: Iterator<Item = &'a Expr<'a>>>(es: &mut T, main_loop_id: HirId) -> NeverLoopResult {
-    es.map(|e| never_loop_expr(e, main_loop_id))
+fn never_loop_expr_all<'a, T: Iterator<Item = &'a Expr<'a>>>(
+    es: &mut T,
+    ignore_ids: &mut Vec<HirId>,
+    main_loop_id: HirId,
+) -> NeverLoopResult {
+    es.map(|e| never_loop_expr(e, ignore_ids, main_loop_id))
         .fold(NeverLoopResult::Otherwise, combine_both)
 }
 
-fn never_loop_expr_branch<'a, T: Iterator<Item = &'a Expr<'a>>>(e: &mut T, main_loop_id: HirId) -> NeverLoopResult {
-    e.map(|e| never_loop_expr(e, main_loop_id))
+fn never_loop_expr_branch<'a, T: Iterator<Item = &'a Expr<'a>>>(
+    e: &mut T,
+    ignore_ids: &mut Vec<HirId>,
+    main_loop_id: HirId,
+) -> NeverLoopResult {
+    e.map(|e| never_loop_expr(e, ignore_ids, main_loop_id))
         .fold(NeverLoopResult::AlwaysBreak, combine_branches)
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index 5c6a342b3d0..6a98df49912 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -177,7 +177,7 @@ fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>)
         if let Some(args) = cx
             .tcx
             .lang_items()
-            .from_generator_fn()
+            .identity_future_fn()
             .and_then(|def_id| match_function_call_with_def_id(cx, block_expr, def_id));
         if args.len() == 1;
         if let Expr {
diff --git a/src/tools/clippy/clippy_lints/src/manual_instant_elapsed.rs b/src/tools/clippy/clippy_lints/src/manual_instant_elapsed.rs
deleted file mode 100644
index 331cda1db89..00000000000
--- a/src/tools/clippy/clippy_lints/src/manual_instant_elapsed.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use rustc_errors::Applicability;
-use rustc_hir::{BinOpKind, Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::source_map::Spanned;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Lints subtraction between `Instant::now()` and another `Instant`.
-    ///
-    /// ### Why is this bad?
-    /// It is easy to accidentally write `prev_instant - Instant::now()`, which will always be 0ns
-    /// as `Instant` subtraction saturates.
-    ///
-    /// `prev_instant.elapsed()` also more clearly signals intention.
-    ///
-    /// ### Example
-    /// ```rust
-    /// use std::time::Instant;
-    /// let prev_instant = Instant::now();
-    /// let duration = Instant::now() - prev_instant;
-    /// ```
-    /// Use instead:
-    /// ```rust
-    /// use std::time::Instant;
-    /// let prev_instant = Instant::now();
-    /// let duration = prev_instant.elapsed();
-    /// ```
-    #[clippy::version = "1.64.0"]
-    pub MANUAL_INSTANT_ELAPSED,
-    pedantic,
-    "subtraction between `Instant::now()` and previous `Instant`"
-}
-
-declare_lint_pass!(ManualInstantElapsed => [MANUAL_INSTANT_ELAPSED]);
-
-impl LateLintPass<'_> for ManualInstantElapsed {
-    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
-        if let ExprKind::Binary(Spanned {node: BinOpKind::Sub, ..}, lhs, rhs) = expr.kind
-            && check_instant_now_call(cx, lhs)
-            && let ty_resolved = cx.typeck_results().expr_ty(rhs)
-            && let rustc_middle::ty::Adt(def, _) = ty_resolved.kind()
-            && clippy_utils::match_def_path(cx, def.did(), &clippy_utils::paths::INSTANT)
-            && let Some(sugg) = clippy_utils::sugg::Sugg::hir_opt(cx, rhs)
-        {
-            span_lint_and_sugg(
-                cx,
-                MANUAL_INSTANT_ELAPSED,
-                expr.span,
-                "manual implementation of `Instant::elapsed`",
-                "try",
-                format!("{}.elapsed()", sugg.maybe_par()),
-                Applicability::MachineApplicable,
-            );
-        }
-    }
-}
-
-fn check_instant_now_call(cx: &LateContext<'_>, expr_block: &'_ Expr<'_>) -> bool {
-    if let ExprKind::Call(fn_expr, []) = expr_block.kind
-        && let Some(fn_id) = clippy_utils::path_def_id(cx, fn_expr)
-        && clippy_utils::match_def_path(cx, fn_id, &clippy_utils::paths::INSTANT_NOW)
-    {
-        true
-    } else {
-        false
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
new file mode 100644
index 00000000000..bb8c142f8e4
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
@@ -0,0 +1,158 @@
+use rustc_ast::LitKind::{Byte, Char};
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{def_id::DefId, sym};
+
+use clippy_utils::{
+    diagnostics::span_lint_and_sugg, in_constant, macros::root_macro_call, meets_msrv, msrvs, source::snippet,
+};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Suggests to use dedicated built-in methods,
+    /// `is_ascii_(lowercase|uppercase|digit)` for checking on corresponding ascii range
+    ///
+    /// ### Why is this bad?
+    /// Using the built-in functions is more readable and makes it
+    /// clear that it's not a specific subset of characters, but all
+    /// ASCII (lowercase|uppercase|digit) characters.
+    /// ### Example
+    /// ```rust
+    /// fn main() {
+    ///     assert!(matches!('x', 'a'..='z'));
+    ///     assert!(matches!(b'X', b'A'..=b'Z'));
+    ///     assert!(matches!('2', '0'..='9'));
+    ///     assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// fn main() {
+    ///     assert!('x'.is_ascii_lowercase());
+    ///     assert!(b'X'.is_ascii_uppercase());
+    ///     assert!('2'.is_ascii_digit());
+    ///     assert!('x'.is_ascii_alphabetic());
+    /// }
+    /// ```
+    #[clippy::version = "1.66.0"]
+    pub MANUAL_IS_ASCII_CHECK,
+    style,
+    "use dedicated method to check ascii range"
+}
+impl_lint_pass!(ManualIsAsciiCheck => [MANUAL_IS_ASCII_CHECK]);
+
+pub struct ManualIsAsciiCheck {
+    msrv: Option<RustcVersion>,
+}
+
+impl ManualIsAsciiCheck {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        Self { msrv }
+    }
+}
+
+#[derive(Debug, PartialEq)]
+enum CharRange {
+    /// 'a'..='z' | b'a'..=b'z'
+    LowerChar,
+    /// 'A'..='Z' | b'A'..=b'Z'
+    UpperChar,
+    /// AsciiLower | AsciiUpper
+    FullChar,
+    /// '0..=9'
+    Digit,
+    Otherwise,
+}
+
+impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        if !meets_msrv(self.msrv, msrvs::IS_ASCII_DIGIT) {
+            return;
+        }
+
+        if in_constant(cx, expr.hir_id) && !meets_msrv(self.msrv, msrvs::IS_ASCII_DIGIT_CONST) {
+            return;
+        }
+
+        let Some(macro_call) = root_macro_call(expr.span) else { return };
+
+        if is_matches_macro(cx, macro_call.def_id) {
+            if let ExprKind::Match(recv, [arm, ..], _) = expr.kind {
+                let range = check_pat(&arm.pat.kind);
+
+                if let Some(sugg) = match range {
+                    CharRange::UpperChar => Some("is_ascii_uppercase"),
+                    CharRange::LowerChar => Some("is_ascii_lowercase"),
+                    CharRange::FullChar => Some("is_ascii_alphabetic"),
+                    CharRange::Digit => Some("is_ascii_digit"),
+                    CharRange::Otherwise => None,
+                } {
+                    let default_snip = "..";
+                    // `snippet_with_applicability` may set applicability to `MaybeIncorrect` for
+                    // macro span, so we check applicability manually by comparing `recv` is not default.
+                    let recv = snippet(cx, recv.span, default_snip);
+
+                    let applicability = if recv == default_snip {
+                        Applicability::HasPlaceholders
+                    } else {
+                        Applicability::MachineApplicable
+                    };
+
+                    span_lint_and_sugg(
+                        cx,
+                        MANUAL_IS_ASCII_CHECK,
+                        macro_call.span,
+                        "manual check for common ascii range",
+                        "try",
+                        format!("{recv}.{sugg}()"),
+                        applicability,
+                    );
+                }
+            }
+        }
+    }
+
+    extract_msrv_attr!(LateContext);
+}
+
+fn check_pat(pat_kind: &PatKind<'_>) -> CharRange {
+    match pat_kind {
+        PatKind::Or(pats) => {
+            let ranges = pats.iter().map(|p| check_pat(&p.kind)).collect::<Vec<_>>();
+
+            if ranges.len() == 2 && ranges.contains(&CharRange::UpperChar) && ranges.contains(&CharRange::LowerChar) {
+                CharRange::FullChar
+            } else {
+                CharRange::Otherwise
+            }
+        },
+        PatKind::Range(Some(start), Some(end), kind) if *kind == RangeEnd::Included => check_range(start, end),
+        _ => CharRange::Otherwise,
+    }
+}
+
+fn check_range(start: &Expr<'_>, end: &Expr<'_>) -> CharRange {
+    if let ExprKind::Lit(start_lit) = &start.kind
+        && let ExprKind::Lit(end_lit) = &end.kind {
+        match (&start_lit.node, &end_lit.node) {
+            (Char('a'), Char('z')) | (Byte(b'a'), Byte(b'z')) => CharRange::LowerChar,
+            (Char('A'), Char('Z')) | (Byte(b'A'), Byte(b'Z')) => CharRange::UpperChar,
+            (Char('0'), Char('9')) | (Byte(b'0'), Byte(b'9')) => CharRange::Digit,
+            _ => CharRange::Otherwise,
+        }
+    } else {
+        CharRange::Otherwise
+    }
+}
+
+fn is_matches_macro(cx: &LateContext<'_>, macro_def_id: DefId) -> bool {
+    if let Some(name) = cx.tcx.get_diagnostic_name(macro_def_id) {
+        return sym::matches_macro == name;
+    }
+
+    false
+}
diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
new file mode 100644
index 00000000000..1846596fa4c
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
@@ -0,0 +1,297 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::higher::IfLetOrMatch;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::{meets_msrv, msrvs, peel_blocks};
+use if_chain::if_chain;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::symbol::sym;
+use rustc_span::Span;
+use serde::Deserialize;
+use std::ops::ControlFlow;
+
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// Warn of cases where `let...else` could be used
+    ///
+    /// ### Why is this bad?
+    ///
+    /// `let...else` provides a standard construct for this pattern
+    /// that people can easily recognize. It's also more compact.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// # let w = Some(0);
+    /// let v = if let Some(v) = w { v } else { return };
+    /// ```
+    ///
+    /// Could be written:
+    ///
+    /// ```rust
+    /// # #![feature(let_else)]
+    /// # fn main () {
+    /// # let w = Some(0);
+    /// let Some(v) = w else { return };
+    /// # }
+    /// ```
+    #[clippy::version = "1.67.0"]
+    pub MANUAL_LET_ELSE,
+    pedantic,
+    "manual implementation of a let...else statement"
+}
+
+pub struct ManualLetElse {
+    msrv: Option<RustcVersion>,
+    matches_behaviour: MatchLintBehaviour,
+}
+
+impl ManualLetElse {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>, matches_behaviour: MatchLintBehaviour) -> Self {
+        Self {
+            msrv,
+            matches_behaviour,
+        }
+    }
+}
+
+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 meets_msrv(self.msrv, 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;
+            }
+        };
+
+        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);
+                }
+            },
+            IfLetOrMatch::Match(match_expr, arms, source) => {
+                if self.matches_behaviour == MatchLintBehaviour::Never {
+                    return;
+                }
+                if source != MatchSource::Normal {
+                    return;
+                }
+                // Any other number than two arms doesn't (neccessarily)
+                // have a trivial mapping to let else.
+                if arms.len() != 2 {
+                    return;
+                }
+                // Guards don't give us an easy mapping either
+                if arms.iter().any(|arm| arm.guard.is_some()) {
+                    return;
+                }
+                let check_types = self.matches_behaviour == MatchLintBehaviour::WellKnownTypes;
+                let diverging_arm_opt = arms
+                    .iter()
+                    .enumerate()
+                    .find(|(_, arm)| expr_diverges(cx, arm.body) && pat_allowed_for_else(cx, arm.pat, check_types));
+                let Some((idx, diverging_arm)) = diverging_arm_opt else { return; };
+                let pat_arm = &arms[1 - idx];
+                if !expr_is_simple_identity(pat_arm.pat, pat_arm.body) {
+                    return;
+                }
+
+                emit_manual_let_else(cx, stmt.span, match_expr, 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<'_>) {
+    span_lint_and_then(
+        cx,
+        MANUAL_LET_ELSE,
+        span,
+        "this could be rewritten as `let...else`",
+        |diag| {
+            // This is far from perfect, for example there needs to be:
+            // * mut additions for the bindings
+            // * renamings of the bindings
+            // * unused binding collision detection with existing ones
+            // * putting patterns with at the top level | inside ()
+            // for this to be machine applicable.
+            let app = Applicability::HasPlaceholders;
+
+            if let Some(sn_pat) = snippet_opt(cx, pat.span) &&
+                let Some(sn_expr) = snippet_opt(cx, expr.span) &&
+                let Some(sn_else) = snippet_opt(cx, else_body.span)
+            {
+                let else_bl = if matches!(else_body.kind, ExprKind::Block(..)) {
+                    sn_else
+                } else {
+                    format!("{{ {sn_else} }}")
+                };
+                let sugg = format!("let {sn_pat} = {sn_expr} else {else_bl};");
+                diag.span_suggestion(span, "consider writing", sugg, app);
+            }
+        },
+    );
+}
+
+fn expr_diverges(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
+    fn is_never(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
+        if let Some(ty) = cx.typeck_results().expr_ty_opt(expr) {
+            return ty.is_never();
+        }
+        false
+    }
+    // We can't just call is_never on expr and be done, because the type system
+    // sometimes coerces the ! type to something different before we can get
+    // our hands on it. So instead, we do a manual search. We do fall back to
+    // is_never in some places when there is no better alternative.
+    for_each_expr(expr, |ex| {
+        match ex.kind {
+            ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => ControlFlow::Break(()),
+            ExprKind::Call(call, _) => {
+                if is_never(cx, ex) || is_never(cx, call) {
+                    return ControlFlow::Break(());
+                }
+                ControlFlow::Continue(Descend::Yes)
+            },
+            ExprKind::MethodCall(..) => {
+                if is_never(cx, ex) {
+                    return ControlFlow::Break(());
+                }
+                ControlFlow::Continue(Descend::Yes)
+            },
+            ExprKind::If(if_expr, if_then, if_else) => {
+                let else_diverges = if_else.map_or(false, |ex| expr_diverges(cx, ex));
+                let diverges = expr_diverges(cx, if_expr) || (else_diverges && expr_diverges(cx, if_then));
+                if diverges {
+                    return ControlFlow::Break(());
+                }
+                ControlFlow::Continue(Descend::No)
+            },
+            ExprKind::Match(match_expr, match_arms, _) => {
+                let diverges = expr_diverges(cx, match_expr)
+                    || match_arms.iter().all(|arm| {
+                        let guard_diverges = arm.guard.as_ref().map_or(false, |g| expr_diverges(cx, g.body()));
+                        guard_diverges || expr_diverges(cx, arm.body)
+                    });
+                if diverges {
+                    return ControlFlow::Break(());
+                }
+                ControlFlow::Continue(Descend::No)
+            },
+
+            // Don't continue into loops or labeled blocks, as they are breakable,
+            // and we'd have to start checking labels.
+            ExprKind::Block(_, Some(_)) | ExprKind::Loop(..) => ControlFlow::Continue(Descend::No),
+
+            // Default: descend
+            _ => ControlFlow::Continue(Descend::Yes),
+        }
+    })
+    .is_some()
+}
+
+fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>, check_types: bool) -> bool {
+    // Check whether the pattern contains any bindings, as the
+    // binding might potentially be used in the body.
+    // TODO: only look for *used* bindings.
+    let mut has_bindings = false;
+    pat.each_binding_or_first(&mut |_, _, _, _| has_bindings = true);
+    if has_bindings {
+        return false;
+    }
+
+    // If we shouldn't check the types, exit early.
+    if !check_types {
+        return true;
+    }
+
+    // Check whether any possibly "unknown" patterns are included,
+    // because users might not know which values some enum has.
+    // Well-known enums are excepted, as we assume people know them.
+    // We do a deep check, to be able to disallow Err(En::Foo(_))
+    // for usage of the En::Foo variant, as we disallow En::Foo(_),
+    // but we allow Err(_).
+    let typeck_results = cx.typeck_results();
+    let mut has_disallowed = false;
+    pat.walk_always(|pat| {
+        // Only do the check if the type is "spelled out" in the pattern
+        if !matches!(
+            pat.kind,
+            PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..)
+        ) {
+            return;
+        };
+        let ty = typeck_results.pat_ty(pat);
+        // Option and Result are allowed, everything else isn't.
+        if !(is_type_diagnostic_item(cx, ty, sym::Option) || is_type_diagnostic_item(cx, ty, sym::Result)) {
+            has_disallowed = true;
+        }
+    });
+    !has_disallowed
+}
+
+/// Checks if the passed block is a simple identity referring to bindings created by the pattern
+fn expr_is_simple_identity(pat: &'_ Pat<'_>, expr: &'_ Expr<'_>) -> bool {
+    // We support patterns with multiple bindings and tuples, like:
+    //   let ... = if let (Some(foo), bar) = g() { (foo, bar) } else { ... }
+    let peeled = peel_blocks(expr);
+    let paths = match peeled.kind {
+        ExprKind::Tup(exprs) | ExprKind::Array(exprs) => exprs,
+        ExprKind::Path(_) => std::slice::from_ref(peeled),
+        _ => return false,
+    };
+    let mut pat_bindings = FxHashSet::default();
+    pat.each_binding_or_first(&mut |_ann, _hir_id, _sp, ident| {
+        pat_bindings.insert(ident);
+    });
+    if pat_bindings.len() < paths.len() {
+        return false;
+    }
+    for path in paths {
+        if_chain! {
+            if let ExprKind::Path(QPath::Resolved(_ty, path)) = path.kind;
+            if let [path_seg] = path.segments;
+            then {
+                if !pat_bindings.remove(&path_seg.ident) {
+                    return false;
+                }
+            } else {
+                return false;
+            }
+        }
+    }
+    true
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize)]
+pub enum MatchLintBehaviour {
+    AllTypes,
+    WellKnownTypes,
+    Never,
+}
diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
index 32da37a862d..59195d1ae4e 100644
--- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
@@ -119,7 +119,7 @@ fn is_unit_expression(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
 /// semicolons, which causes problems when generating a suggestion. Given an
 /// expression that evaluates to '()' or '!', recursively remove useless braces
 /// and semi-colons until is suitable for including in the suggestion template
-fn reduce_unit_expression<'a>(cx: &LateContext<'_>, expr: &'a hir::Expr<'_>) -> Option<Span> {
+fn reduce_unit_expression(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Span> {
     if !is_unit_expression(cx, expr) {
         return None;
     }
diff --git a/src/tools/clippy/clippy_lints/src/matches/infallible_destructuring_match.rs b/src/tools/clippy/clippy_lints/src/matches/infallible_destructuring_match.rs
index 2472acb6f6e..d18c92caba2 100644
--- a/src/tools/clippy/clippy_lints/src/matches/infallible_destructuring_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/infallible_destructuring_match.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{path_to_local_id, peel_blocks, strip_pat_refs};
 use rustc_errors::Applicability;
-use rustc_hir::{ExprKind, Local, MatchSource, PatKind, QPath};
+use rustc_hir::{ByRef, ExprKind, Local, MatchSource, PatKind, QPath};
 use rustc_lint::LateContext;
 
 use super::INFALLIBLE_DESTRUCTURING_MATCH;
@@ -16,7 +16,7 @@ pub(crate) fn check(cx: &LateContext<'_>, local: &Local<'_>) -> bool {
         if let PatKind::TupleStruct(
             QPath::Resolved(None, variant_name), args, _) = arms[0].pat.kind;
         if args.len() == 1;
-        if let PatKind::Binding(_, arg, ..) = strip_pat_refs(&args[0]).kind;
+        if let PatKind::Binding(binding, arg, ..) = strip_pat_refs(&args[0]).kind;
         let body = peel_blocks(arms[0].body);
         if path_to_local_id(body, arg);
 
@@ -30,8 +30,9 @@ pub(crate) fn check(cx: &LateContext<'_>, local: &Local<'_>) -> bool {
                 Consider using `let`",
                 "try this",
                 format!(
-                    "let {}({}) = {};",
+                    "let {}({}{}) = {};",
                     snippet_with_applicability(cx, variant_name.span, "..", &mut applicability),
+                    if binding.0 == ByRef::Yes { "ref " } else { "" },
                     snippet_with_applicability(cx, local.pat.span, "..", &mut applicability),
                     snippet_with_applicability(cx, target.span, "..", &mut applicability),
                 ),
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs
index 66ba1f6f9c5..d521a529e0d 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs
@@ -62,7 +62,7 @@ fn peels_blocks_incl_unsafe<'a>(expr: &'a Expr<'a>) -> &'a Expr<'a> {
 //    <expr>
 // }
 // Returns true if <expr> resolves to `Some(x)`, `false` otherwise
-fn is_some_expr<'tcx>(cx: &LateContext<'_>, target: HirId, ctxt: SyntaxContext, expr: &'tcx Expr<'_>) -> bool {
+fn is_some_expr(cx: &LateContext<'_>, target: HirId, ctxt: SyntaxContext, expr: &Expr<'_>) -> bool {
     if let Some(inner_expr) = peels_blocks_incl_unsafe_opt(expr) {
         // there can be not statements in the block as they would be removed when switching to `.filter`
         if let ExprKind::Call(callee, [arg]) = inner_expr.kind {
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
index 6f8d766aef7..7f8d124838c 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
@@ -65,14 +65,14 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
                         _ => return,
                     };
                     if arm.guard.is_none() {
-                        missing_variants.retain(|e| e.ctor_def_id != Some(id));
+                        missing_variants.retain(|e| e.ctor_def_id() != Some(id));
                     }
                     path
                 },
                 PatKind::TupleStruct(path, patterns, ..) => {
                     if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id() {
                         if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p)) {
-                            missing_variants.retain(|e| e.ctor_def_id != Some(id));
+                            missing_variants.retain(|e| e.ctor_def_id() != Some(id));
                         }
                     }
                     path
@@ -122,11 +122,11 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
                 s
             },
             variant.name,
-            match variant.ctor_kind {
-                CtorKind::Fn if variant.fields.len() == 1 => "(_)",
-                CtorKind::Fn => "(..)",
-                CtorKind::Const => "",
-                CtorKind::Fictive => "{ .. }",
+            match variant.ctor_kind() {
+                Some(CtorKind::Fn) if variant.fields.len() == 1 => "(_)",
+                Some(CtorKind::Fn) => "(..)",
+                Some(CtorKind::Const) => "",
+                None => "{ .. }",
             }
         )
     };
diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index 85269e533a0..f587c69f730 100644
--- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -83,8 +83,8 @@ fn set_diagnostic<'tcx>(diag: &mut Diagnostic, cx: &LateContext<'tcx>, expr: &'t
 
 /// If the expression is an `ExprKind::Match`, check if the scrutinee has a significant drop that
 /// may have a surprising lifetime.
-fn has_significant_drop_in_scrutinee<'tcx, 'a>(
-    cx: &'a LateContext<'tcx>,
+fn has_significant_drop_in_scrutinee<'tcx>(
+    cx: &LateContext<'tcx>,
     scrutinee: &'tcx Expr<'tcx>,
     source: MatchSource,
 ) -> Option<(Vec<FoundSigDrop>, &'static str)> {
@@ -226,7 +226,7 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> {
     /// This will try to set the current suggestion (so it can be moved into the suggestions vec
     /// later). If `allow_move_and_clone` is false, the suggestion *won't* be set -- this gives us
     /// an opportunity to look for another type in the chain that will be trivially copyable.
-    /// However, if we are at the the end of the chain, we want to accept whatever is there. (The
+    /// However, if we are at the end of the chain, we want to accept whatever is there. (The
     /// suggestion won't actually be output, but the diagnostic message will be output, so the user
     /// can determine the best way to handle the lint.)
     fn try_setting_current_suggestion(&mut self, expr: &'tcx Expr<'_>, allow_move_and_clone: bool) {
@@ -377,7 +377,7 @@ impl<'a, 'tcx> ArmSigDropHelper<'a, 'tcx> {
     }
 }
 
-fn has_significant_drop_in_arms<'tcx, 'a>(cx: &'a LateContext<'tcx>, arms: &'tcx [Arm<'_>]) -> FxHashSet<Span> {
+fn has_significant_drop_in_arms<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) -> FxHashSet<Span> {
     let mut helper = ArmSigDropHelper::new(cx);
     for arm in arms {
         helper.visit_expr(arm.body);
diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
index e5a15b2e1a1..19b49c44d57 100644
--- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
@@ -153,7 +153,7 @@ fn pat_in_candidate_enum<'a>(cx: &LateContext<'a>, ty: Ty<'a>, pat: &Pat<'_>) ->
 }
 
 /// Returns `true` if the given type is an enum we know won't be expanded in the future
-fn in_candidate_enum<'a>(cx: &LateContext<'a>, ty: Ty<'_>) -> bool {
+fn in_candidate_enum(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
     // list of candidate `Enum`s we know will never get any more members
     let candidates = [sym::Cow, sym::Option, sym::Result];
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
index 7e808760663..27a05337a29 100644
--- a/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
@@ -9,8 +9,8 @@ use rustc_lint::LateContext;
 use rustc_lint::Lint;
 
 /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`.
-pub(super) fn check<'tcx>(
-    cx: &LateContext<'tcx>,
+pub(super) fn check(
+    cx: &LateContext<'_>,
     info: &crate::methods::BinaryExprInfo<'_>,
     chain_methods: &[&str],
     lint: &'static Lint,
diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp.rs b/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp.rs
index 07bbc5ca1bf..2efff4c3c54 100644
--- a/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp.rs
@@ -4,7 +4,7 @@ use rustc_lint::LateContext;
 use super::CHARS_LAST_CMP;
 
 /// Checks for the `CHARS_LAST_CMP` lint.
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, info: &crate::methods::BinaryExprInfo<'_>) -> bool {
+pub(super) fn check(cx: &LateContext<'_>, info: &crate::methods::BinaryExprInfo<'_>) -> bool {
     if chars_cmp::check(cx, info, &["chars", "last"], CHARS_LAST_CMP, "ends_with") {
         true
     } else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs
index c29ee0ec8c8..5b8713f7d79 100644
--- a/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs
@@ -4,7 +4,7 @@ use rustc_lint::LateContext;
 use super::CHARS_LAST_CMP;
 
 /// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`.
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, info: &crate::methods::BinaryExprInfo<'_>) -> bool {
+pub(super) fn check(cx: &LateContext<'_>, info: &crate::methods::BinaryExprInfo<'_>) -> bool {
     if chars_cmp_with_unwrap::check(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") {
         true
     } else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp.rs b/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp.rs
index a6701d8830e..b631fecab97 100644
--- a/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp.rs
@@ -3,6 +3,6 @@ use rustc_lint::LateContext;
 use super::CHARS_NEXT_CMP;
 
 /// Checks for the `CHARS_NEXT_CMP` lint.
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, info: &crate::methods::BinaryExprInfo<'_>) -> bool {
+pub(super) fn check(cx: &LateContext<'_>, info: &crate::methods::BinaryExprInfo<'_>) -> bool {
     crate::methods::chars_cmp::check(cx, info, &["chars", "next"], CHARS_NEXT_CMP, "starts_with")
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs
index 28ede28e935..caf21d3ff3b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs
@@ -3,6 +3,6 @@ use rustc_lint::LateContext;
 use super::CHARS_NEXT_CMP;
 
 /// Checks for the `CHARS_NEXT_CMP` lint with `unwrap()`.
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, info: &crate::methods::BinaryExprInfo<'_>) -> bool {
+pub(super) fn check(cx: &LateContext<'_>, info: &crate::methods::BinaryExprInfo<'_>) -> bool {
     crate::methods::chars_cmp_with_unwrap::check(cx, info, &["chars", "next", "unwrap"], CHARS_NEXT_CMP, "starts_with")
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs b/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
index 501646863fe..ac61b437788 100644
--- a/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(
         // If the parent node's `to` argument is the same as the `to` argument
         // of the last replace call in the current chain, don't lint as it was already linted
         if let Some(parent) = get_parent_expr(cx, expr)
-            && let Some(("replace", _, [current_from, current_to], _)) = method_call(parent)
+            && let Some(("replace", _, [current_from, current_to], _, _)) = method_call(parent)
             && eq_expr_value(cx, to, current_to)
             && from_kind == cx.typeck_results().expr_ty(current_from).peel_refs().kind()
         {
@@ -48,7 +48,7 @@ fn collect_replace_calls<'tcx>(
     let mut from_args = VecDeque::new();
 
     let _: Option<()> = for_each_expr(expr, |e| {
-        if let Some(("replace", _, [from, to], _)) = method_call(e) {
+        if let Some(("replace", _, [from, to], _, _)) = method_call(e) {
             if eq_expr_value(cx, to_arg, to) && cx.typeck_results().expr_ty(from).peel_refs().is_char() {
                 methods.push_front(e);
                 from_args.push_front(from);
@@ -78,7 +78,7 @@ fn check_consecutive_replace_calls<'tcx>(
         .collect();
     let app = Applicability::MachineApplicable;
     let earliest_replace_call = replace_methods.methods.front().unwrap();
-    if let Some((_, _, [..], span_lo)) = method_call(earliest_replace_call) {
+    if let Some((_, _, [..], span_lo, _)) = method_call(earliest_replace_call) {
         span_lint_and_sugg(
             cx,
             COLLAPSIBLE_STR_REPLACE,
diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_used.rs b/src/tools/clippy/clippy_lints/src/methods/expect_used.rs
index d59fefa1ddc..cce8f797e98 100644
--- a/src/tools/clippy/clippy_lints/src/methods/expect_used.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/expect_used.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::is_in_test_function;
+use clippy_utils::is_in_cfg_test;
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -18,16 +18,16 @@ pub(super) fn check(
     let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs();
 
     let mess = if is_type_diagnostic_item(cx, obj_ty, sym::Option) && !is_err {
-        Some((EXPECT_USED, "an Option", "None", ""))
+        Some((EXPECT_USED, "an `Option`", "None", ""))
     } else if is_type_diagnostic_item(cx, obj_ty, sym::Result) {
-        Some((EXPECT_USED, "a Result", if is_err { "Ok" } else { "Err" }, "an "))
+        Some((EXPECT_USED, "a `Result`", if is_err { "Ok" } else { "Err" }, "an "))
     } else {
         None
     };
 
     let method = if is_err { "expect_err" } else { "expect" };
 
-    if allow_expect_in_tests && is_in_test_function(cx.tcx, expr.hir_id) {
+    if allow_expect_in_tests && is_in_cfg_test(cx.tcx, expr.hir_id) {
         return;
     }
 
@@ -36,7 +36,7 @@ pub(super) fn check(
             cx,
             lint,
             expr.span,
-            &format!("used `{method}()` on `{kind}` value"),
+            &format!("used `{method}()` on {kind} value"),
             None,
             &format!("if this value is {none_prefix}`{none_value}`, it will panic"),
         );
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
index 9719b2f1c51..f888c58a72d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
@@ -17,7 +17,7 @@ use super::MANUAL_FILTER_MAP;
 use super::MANUAL_FIND_MAP;
 use super::OPTION_FILTER_MAP;
 
-fn is_method<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Symbol) -> bool {
+fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> bool {
     match &expr.kind {
         hir::ExprKind::Path(QPath::TypeRelative(_, mname)) => mname.ident.name == method_name,
         hir::ExprKind::Path(QPath::Resolved(_, segments)) => {
@@ -46,7 +46,7 @@ fn is_method<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Sy
     }
 }
 
-fn is_option_filter_map<'tcx>(cx: &LateContext<'tcx>, filter_arg: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) -> bool {
+fn is_option_filter_map(cx: &LateContext<'_>, filter_arg: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) -> bool {
     is_method(cx, map_arg, sym::unwrap) && is_method(cx, filter_arg, sym!(is_some))
 }
 
@@ -66,8 +66,8 @@ fn is_filter_some_map_unwrap(
 
 /// lint use of `filter().map()` or `find().map()` for `Iterators`
 #[allow(clippy::too_many_arguments)]
-pub(super) fn check<'tcx>(
-    cx: &LateContext<'tcx>,
+pub(super) fn check(
+    cx: &LateContext<'_>,
     expr: &hir::Expr<'_>,
     filter_recv: &hir::Expr<'_>,
     filter_arg: &hir::Expr<'_>,
diff --git a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
index 4f4f543e8a9..d8c821bc9ee 100644
--- a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
@@ -12,8 +12,8 @@ use rustc_span::symbol::{Symbol, sym};
 use super::INEFFICIENT_TO_STRING;
 
 /// Checks for the `INEFFICIENT_TO_STRING` lint
-pub fn check<'tcx>(
-    cx: &LateContext<'tcx>,
+pub fn check(
+    cx: &LateContext<'_>,
     expr: &hir::Expr<'_>,
     method_name: Symbol,
     receiver: &hir::Expr<'_>,
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 68d906c3ea3..c830958d5c8 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
@@ -10,7 +10,7 @@ use rustc_span::sym;
 
 use super::ITER_NTH_ZERO;
 
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) {
+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);
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
index 4f73b3ec422..70abe4891d9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
@@ -25,7 +25,7 @@ impl IterType {
     }
 }
 
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, method_name: &str, recv: &Expr<'_>) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, recv: &Expr<'_>) {
     let item = match recv.kind {
         ExprKind::Array([]) => None,
         ExprKind::Array([e]) => Some(e),
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
index 06a39c5997e..b4210d87510 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::{get_associated_type, implements_trait, is_copy};
+use clippy_utils::ty::{implements_trait, is_copy};
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
@@ -25,7 +25,7 @@ pub(super) fn check<'tcx>(
         && let Some(method_id) = typeck.type_dependent_def_id(cloned_call.hir_id)
         && cx.tcx.trait_of_item(method_id) == Some(iter_id)
         && let cloned_recv_ty = typeck.expr_ty_adjusted(cloned_recv)
-        && let Some(iter_assoc_ty) = get_associated_type(cx, cloned_recv_ty, iter_id, "Item")
+        && let Some(iter_assoc_ty) = cx.get_associated_type(cloned_recv_ty, iter_id, "Item")
         && matches!(*iter_assoc_ty.kind(), ty::Ref(_, ty, _) if !is_copy(cx, ty))
     {
         if needs_into_iter
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
index b80541b8647..a7284c64497 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
@@ -67,7 +67,7 @@ enum MinMax {
     Max,
 }
 
-fn is_min_or_max<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) -> Option<MinMax> {
+fn is_min_or_max(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<MinMax> {
     // `T::max_value()` `T::min_value()` inherent methods
     if_chain! {
         if let hir::ExprKind::Call(func, args) = &expr.kind;
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
index 13c47c03a80..a08f7254053 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
@@ -59,10 +59,8 @@ pub(super) fn check(
         if let ExprKind::Call(repeat_fn, [repeat_arg]) = take_self_arg.kind;
         if is_path_diagnostic_item(cx, repeat_fn, sym::iter_repeat);
         if is_type_lang_item(cx, cx.typeck_results().expr_ty(collect_expr), LangItem::String);
-        if let Some(collect_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id);
         if let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id);
         if let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
-        if cx.tcx.trait_of_item(collect_id) == Some(iter_trait_id);
         if cx.tcx.trait_of_item(take_id) == Some(iter_trait_id);
         if let Some(repeat_kind) = parse_repeat_arg(cx, repeat_arg);
         let ctxt = collect_expr.span.ctxt();
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
index 7ce14ec080b..6bc783c6d50 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -15,11 +15,11 @@ use rustc_span::{sym, Span};
 
 use super::MAP_CLONE;
 
-pub(super) fn check<'tcx>(
+pub(super) fn check(
     cx: &LateContext<'_>,
     e: &hir::Expr<'_>,
     recv: &hir::Expr<'_>,
-    arg: &'tcx hir::Expr<'_>,
+    arg: &hir::Expr<'_>,
     msrv: Option<RustcVersion>,
 ) {
     if_chain! {
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs b/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs
index d420f144eea..a0300d27870 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs
@@ -1,5 +1,4 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_trait_method;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
 use if_chain::if_chain;
@@ -11,18 +10,10 @@ use rustc_span::symbol::sym;
 
 use super::MAP_COLLECT_RESULT_UNIT;
 
-pub(super) fn check(
-    cx: &LateContext<'_>,
-    expr: &hir::Expr<'_>,
-    iter: &hir::Expr<'_>,
-    map_fn: &hir::Expr<'_>,
-    collect_recv: &hir::Expr<'_>,
-) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, iter: &hir::Expr<'_>, map_fn: &hir::Expr<'_>) {
+    // return of collect `Result<(),_>`
+    let collect_ret_ty = cx.typeck_results().expr_ty(expr);
     if_chain! {
-        // called on Iterator
-        if is_trait_method(cx, collect_recv, sym::Iterator);
-        // return of collect `Result<(),_>`
-        let collect_ret_ty = cx.typeck_results().expr_ty(expr);
         if is_type_diagnostic_item(cx, collect_ret_ty, sym::Result);
         if let ty::Adt(_, substs) = collect_ret_ty.kind();
         if let Some(result_t) = substs.types().next();
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs b/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
index 1fb6617145e..b773b3e423f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
@@ -6,7 +6,7 @@ use rustc_span::sym;
 
 use super::MAP_ERR_IGNORE;
 
-pub(super) fn check<'tcx>(cx: &LateContext<'_>, e: &Expr<'_>, arg: &'tcx Expr<'_>) {
+pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, arg: &Expr<'_>) {
     if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
         && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
         && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::Result)
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 8a76ba0b064..38165ab4fb2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -54,6 +54,7 @@ mod map_flatten;
 mod map_identity;
 mod map_unwrap_or;
 mod mut_mutex_lock;
+mod needless_collect;
 mod needless_option_as_deref;
 mod needless_option_take;
 mod no_effect_replace;
@@ -69,6 +70,8 @@ mod path_buf_push_overwrite;
 mod range_zip_with_len;
 mod repeat_once;
 mod search_is_some;
+mod seek_from_current;
+mod seek_to_start_instead_of_rewind;
 mod single_char_add_str;
 mod single_char_insert_string;
 mod single_char_pattern;
@@ -101,12 +104,11 @@ mod zst_offset;
 use bind_instead_of_map::BindInsteadOfMap;
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
-use clippy_utils::ty::{contains_adt_constructor, implements_trait, is_copy, is_type_diagnostic_item};
-use clippy_utils::{contains_return, is_trait_method, iter_input_pats, meets_msrv, msrvs, return_ty};
+use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item};
+use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, meets_msrv, msrvs, return_ty};
 use if_chain::if_chain;
 use rustc_hir as hir;
-use rustc_hir::def::Res;
-use rustc_hir::{Expr, ExprKind, PrimTy, QPath, TraitItem, TraitItemKind};
+use rustc_hir::{Expr, ExprKind, TraitItem, TraitItemKind};
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
@@ -156,9 +158,9 @@ declare_clippy_lint! {
     /// ```
     /// Use instead:
     /// ```rust
-    /// let hello = "hesuo worpd".replace(&['s', 'u', 'p'], "l");
+    /// let hello = "hesuo worpd".replace(['s', 'u', 'p'], "l");
     /// ```
-    #[clippy::version = "1.64.0"]
+    #[clippy::version = "1.65.0"]
     pub COLLAPSIBLE_STR_REPLACE,
     perf,
     "collapse consecutive calls to str::replace (2 or more) into a single call"
@@ -829,32 +831,30 @@ declare_clippy_lint! {
     /// etc. instead.
     ///
     /// ### Why is this bad?
-    /// The function will always be called and potentially
-    /// allocate an object acting as the default.
+    /// The function will always be called. This is only bad if it allocates or
+    /// does some non-trivial amount of work.
     ///
     /// ### Known problems
-    /// If the function has side-effects, not calling it will
-    /// change the semantic of the program, but you shouldn't rely on that anyway.
+    /// If the function has side-effects, not calling it will change the
+    /// semantic of the program, but you shouldn't rely on that.
+    ///
+    /// The lint also cannot figure out whether the function you call is
+    /// actually expensive to call or not.
     ///
     /// ### Example
     /// ```rust
     /// # let foo = Some(String::new());
-    /// foo.unwrap_or(String::new());
+    /// foo.unwrap_or(String::from("empty"));
     /// ```
     ///
     /// Use instead:
     /// ```rust
     /// # let foo = Some(String::new());
-    /// foo.unwrap_or_else(String::new);
-    ///
-    /// // or
-    ///
-    /// # let foo = Some(String::new());
-    /// foo.unwrap_or_default();
+    /// foo.unwrap_or_else(|| String::from("empty"));
     /// ```
     #[clippy::version = "pre 1.29.0"]
     pub OR_FUN_CALL,
-    perf,
+    nursery,
     "using any `*or` method with a function call, which suggests `*or_else`"
 }
 
@@ -1728,7 +1728,7 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for usage of `_.as_ref().map(Deref::deref)` or it's aliases (such as String::as_str).
+    /// Checks for usage of `_.as_ref().map(Deref::deref)` or its aliases (such as String::as_str).
     ///
     /// ### Why is this bad?
     /// Readability, this can be written more concisely as
@@ -2094,8 +2094,7 @@ declare_clippy_lint! {
     /// let s = "Hello world!";
     /// let cow = Cow::Borrowed(s);
     ///
-    /// let data = cow.into_owned();
-    /// assert!(matches!(data, String))
+    /// let _data: String = cow.into_owned();
     /// ```
     #[clippy::version = "1.65.0"]
     pub SUSPICIOUS_TO_OWNED,
@@ -2426,7 +2425,7 @@ declare_clippy_lint! {
     /// ### Known problems
     ///
     /// The type of the resulting iterator might become incompatible with its usage
-    #[clippy::version = "1.64.0"]
+    #[clippy::version = "1.65.0"]
     pub ITER_ON_SINGLE_ITEMS,
     nursery,
     "Iterator for array of length 1"
@@ -2458,7 +2457,7 @@ declare_clippy_lint! {
     /// ### Known problems
     ///
     /// The type of the resulting iterator might become incompatible with its usage
-    #[clippy::version = "1.64.0"]
+    #[clippy::version = "1.65.0"]
     pub ITER_ON_EMPTY_COLLECTIONS,
     nursery,
     "Iterator for empty array"
@@ -3066,6 +3065,102 @@ declare_clippy_lint! {
     "iterating on map using `iter` when `keys` or `values` would do"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// Checks an argument of `seek` method of `Seek` trait
+    /// and if it start seek from `SeekFrom::Current(0)`, suggests `stream_position` instead.
+    ///
+    /// ### Why is this bad?
+    ///
+    /// Readability. Use dedicated method.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,no_run
+    /// use std::fs::File;
+    /// use std::io::{self, Write, Seek, SeekFrom};
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut f = File::create("foo.txt")?;
+    ///     f.write_all(b"Hello")?;
+    ///     eprintln!("Written {} bytes", f.seek(SeekFrom::Current(0))?);
+    ///
+    ///     Ok(())
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust,no_run
+    /// use std::fs::File;
+    /// use std::io::{self, Write, Seek, SeekFrom};
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut f = File::create("foo.txt")?;
+    ///     f.write_all(b"Hello")?;
+    ///     eprintln!("Written {} bytes", f.stream_position()?);
+    ///
+    ///     Ok(())
+    /// }
+    /// ```
+    #[clippy::version = "1.66.0"]
+    pub SEEK_FROM_CURRENT,
+    complexity,
+    "use dedicated method for seek from current position"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// Checks for jumps to the start of a stream that implements `Seek`
+    /// and uses the `seek` method providing `Start` as parameter.
+    ///
+    /// ### Why is this bad?
+    ///
+    /// Readability. There is a specific method that was implemented for
+    /// this exact scenario.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # use std::io;
+    /// fn foo<T: io::Seek>(t: &mut T) {
+    ///     t.seek(io::SeekFrom::Start(0));
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # use std::io;
+    /// fn foo<T: io::Seek>(t: &mut T) {
+    ///     t.rewind();
+    /// }
+    /// ```
+    #[clippy::version = "1.66.0"]
+    pub SEEK_TO_START_INSTEAD_OF_REWIND,
+    complexity,
+    "jumping to the start of stream using `seek` method"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for functions collecting an iterator when collect
+    /// is not needed.
+    ///
+    /// ### Why is this bad?
+    /// `collect` causes the allocation of a new data structure,
+    /// when this allocation may not be needed.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # let iterator = vec![1].into_iter();
+    /// let len = iterator.clone().collect::<Vec<_>>().len();
+    /// // should be
+    /// let len = iterator.count();
+    /// ```
+    #[clippy::version = "1.30.0"]
+    pub NEEDLESS_COLLECT,
+    nursery,
+    "collecting an iterator when collect is not needed"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Option<RustcVersion>,
@@ -3190,16 +3285,19 @@ impl_lint_pass!(Methods => [
     VEC_RESIZE_TO_ZERO,
     VERBOSE_FILE_READS,
     ITER_KV_MAP,
+    SEEK_FROM_CURRENT,
+    SEEK_TO_START_INSTEAD_OF_REWIND,
+    NEEDLESS_COLLECT,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
 fn method_call<'tcx>(
     recv: &'tcx hir::Expr<'tcx>,
-) -> Option<(&'tcx str, &'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>], Span)> {
-    if let ExprKind::MethodCall(path, receiver, args, _) = recv.kind {
+) -> Option<(&'tcx str, &'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>], Span, Span)> {
+    if let ExprKind::MethodCall(path, receiver, args, call_span) = recv.kind {
         if !args.iter().any(|e| e.span.from_expansion()) && !receiver.span.from_expansion() {
             let name = path.ident.name.as_str();
-            return Some((name, receiver, args, path.ident.span));
+            return Some((name, receiver, args, path.ident.span, call_span));
         }
     }
     None
@@ -3316,36 +3414,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
         if let hir::ImplItemKind::Fn(_, _) = impl_item.kind {
             let ret_ty = return_ty(cx, impl_item.hir_id());
 
-            // walk the return type and check for Self (this does not check associated types)
-            if let Some(self_adt) = self_ty.ty_adt_def() {
-                if contains_adt_constructor(ret_ty, self_adt) {
-                    return;
-                }
-            } else if ret_ty.contains(self_ty) {
+            if contains_ty_adt_constructor_opaque(cx, ret_ty, self_ty) {
                 return;
             }
 
-            // if return type is impl trait, check the associated types
-            if let ty::Opaque(def_id, _) = *ret_ty.kind() {
-                // one of the associated types must be Self
-                for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
-                    if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
-                        let assoc_ty = match projection_predicate.term.unpack() {
-                            ty::TermKind::Ty(ty) => ty,
-                            ty::TermKind::Const(_c) => continue,
-                        };
-                        // walk the associated type and check for Self
-                        if let Some(self_adt) = self_ty.ty_adt_def() {
-                            if contains_adt_constructor(assoc_ty, self_adt) {
-                                return;
-                            }
-                        } else if assoc_ty.contains(self_ty) {
-                            return;
-                        }
-                    }
-                }
-            }
-
             if name == "new" && ret_ty != self_ty {
                 span_lint(
                     cx,
@@ -3411,7 +3483,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
 impl Methods {
     #[allow(clippy::too_many_lines)]
     fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let Some((name, recv, args, span)) = method_call(expr) {
+        if let Some((name, recv, args, span, call_span)) = method_call(expr) {
             match (name, args) {
                 ("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [_arg]) => {
                     zst_offset::check(cx, expr, recv);
@@ -3430,28 +3502,31 @@ impl Methods {
                 ("as_ref", []) => useless_asref::check(cx, expr, "as_ref", recv),
                 ("assume_init", []) => uninit_assumed_init::check(cx, expr, recv),
                 ("cloned", []) => cloned_instead_of_copied::check(cx, expr, recv, span, self.msrv),
-                ("collect", []) => match method_call(recv) {
-                    Some((name @ ("cloned" | "copied"), recv2, [], _)) => {
-                        iter_cloned_collect::check(cx, name, expr, recv2);
-                    },
-                    Some(("map", m_recv, [m_arg], _)) => {
-                        map_collect_result_unit::check(cx, expr, m_recv, m_arg, recv);
-                    },
-                    Some(("take", take_self_arg, [take_arg], _)) => {
-                        if meets_msrv(self.msrv, msrvs::STR_REPEAT) {
-                            manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg);
-                        }
-                    },
-                    _ => {},
+                ("collect", []) if is_trait_method(cx, expr, sym::Iterator) => {
+                    needless_collect::check(cx, span, expr, recv, call_span);
+                    match method_call(recv) {
+                        Some((name @ ("cloned" | "copied"), recv2, [], _, _)) => {
+                            iter_cloned_collect::check(cx, name, expr, recv2);
+                        },
+                        Some(("map", m_recv, [m_arg], _, _)) => {
+                            map_collect_result_unit::check(cx, expr, m_recv, m_arg);
+                        },
+                        Some(("take", take_self_arg, [take_arg], _, _)) => {
+                            if meets_msrv(self.msrv, msrvs::STR_REPEAT) {
+                                manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg);
+                            }
+                        },
+                        _ => {},
+                    }
                 },
                 ("count", []) if is_trait_method(cx, expr, sym::Iterator) => match method_call(recv) {
-                    Some(("cloned", recv2, [], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, true, false),
-                    Some((name2 @ ("into_iter" | "iter" | "iter_mut"), recv2, [], _)) => {
+                    Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, true, false),
+                    Some((name2 @ ("into_iter" | "iter" | "iter_mut"), recv2, [], _, _)) => {
                         iter_count::check(cx, expr, recv2, name2);
                     },
-                    Some(("map", _, [arg], _)) => suspicious_map::check(cx, expr, recv, arg),
-                    Some(("filter", recv2, [arg], _)) => bytecount::check(cx, expr, recv2, arg),
-                    Some(("bytes", recv2, [], _)) => bytes_count_to_len::check(cx, expr, recv, recv2),
+                    Some(("map", _, [arg], _, _)) => suspicious_map::check(cx, expr, recv, arg),
+                    Some(("filter", recv2, [arg], _, _)) => bytecount::check(cx, expr, recv2, arg),
+                    Some(("bytes", recv2, [], _, _)) => bytes_count_to_len::check(cx, expr, recv, recv2),
                     _ => {},
                 },
                 ("drain", [arg]) => {
@@ -3463,8 +3538,8 @@ impl Methods {
                     }
                 },
                 ("expect", [_]) => match method_call(recv) {
-                    Some(("ok", recv, [], _)) => ok_expect::check(cx, expr, recv),
-                    Some(("err", recv, [], err_span)) => err_expect::check(cx, expr, recv, self.msrv, span, err_span),
+                    Some(("ok", recv, [], _, _)) => ok_expect::check(cx, expr, recv),
+                    Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, self.msrv, span, err_span),
                     _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests),
                 },
                 ("expect_err", [_]) => expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests),
@@ -3484,13 +3559,13 @@ impl Methods {
                     flat_map_option::check(cx, expr, arg, span);
                 },
                 ("flatten", []) => match method_call(recv) {
-                    Some(("map", recv, [map_arg], map_span)) => map_flatten::check(cx, expr, recv, map_arg, map_span),
-                    Some(("cloned", recv2, [], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, true),
+                    Some(("map", recv, [map_arg], map_span, _)) => map_flatten::check(cx, expr, recv, map_arg, map_span),
+                    Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, true),
                     _ => {},
                 },
                 ("fold", [init, acc]) => unnecessary_fold::check(cx, expr, init, acc, span),
                 ("for_each", [_]) => {
-                    if let Some(("inspect", _, [_], span2)) = method_call(recv) {
+                    if let Some(("inspect", _, [_], span2, _)) = method_call(recv) {
                         inspect_for_each::check(cx, expr, span2);
                     }
                 },
@@ -3510,12 +3585,12 @@ impl Methods {
                     iter_on_single_or_empty_collections::check(cx, expr, name, recv);
                 },
                 ("join", [join_arg]) => {
-                    if let Some(("collect", _, _, span)) = method_call(recv) {
+                    if let Some(("collect", _, _, span, _)) = method_call(recv) {
                         unnecessary_join::check(cx, expr, recv, join_arg, span);
                     }
                 },
                 ("last", []) | ("skip", [_]) => {
-                    if let Some((name2, recv2, args2, _span2)) = method_call(recv) {
+                    if let Some((name2, recv2, args2, _span2, _)) = method_call(recv) {
                         if let ("cloned", []) = (name2, args2) {
                             iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
                         }
@@ -3527,13 +3602,13 @@ impl Methods {
                 (name @ ("map" | "map_err"), [m_arg]) => {
                     if name == "map" {
                         map_clone::check(cx, expr, recv, m_arg, self.msrv);
-                        if let Some((map_name @ ("iter" | "into_iter"), recv2, _, _)) = method_call(recv) {
+                        if let Some((map_name @ ("iter" | "into_iter"), recv2, _, _, _)) = method_call(recv) {
                             iter_kv_map::check(cx, map_name, expr, recv2, m_arg);
                         }
                     } else {
                         map_err_ignore::check(cx, expr, m_arg);
                     }
-                    if let Some((name, recv2, args, span2)) = method_call(recv) {
+                    if let Some((name, recv2, args, span2,_)) = method_call(recv) {
                         match (name, args) {
                             ("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, self.msrv),
                             ("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, self.msrv),
@@ -3553,7 +3628,7 @@ impl Methods {
                     manual_ok_or::check(cx, expr, recv, def, map);
                 },
                 ("next", []) => {
-                    if let Some((name2, recv2, args2, _)) = method_call(recv) {
+                    if let Some((name2, recv2, args2, _, _)) = method_call(recv) {
                         match (name2, args2) {
                             ("cloned", []) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
                             ("filter", [arg]) => filter_next::check(cx, expr, recv2, arg),
@@ -3566,10 +3641,10 @@ impl Methods {
                     }
                 },
                 ("nth", [n_arg]) => match method_call(recv) {
-                    Some(("bytes", recv2, [], _)) => bytes_nth::check(cx, expr, recv2, n_arg),
-                    Some(("cloned", recv2, [], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
-                    Some(("iter", recv2, [], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false),
-                    Some(("iter_mut", recv2, [], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true),
+                    Some(("bytes", recv2, [], _, _)) => bytes_nth::check(cx, expr, recv2, n_arg),
+                    Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
+                    Some(("iter", recv2, [], _, _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false),
+                    Some(("iter_mut", recv2, [], _, _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true),
                     _ => iter_nth_zero::check(cx, expr, recv, n_arg),
                 },
                 ("ok_or_else", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "ok_or"),
@@ -3604,6 +3679,14 @@ impl Methods {
                 ("resize", [count_arg, default_arg]) => {
                     vec_resize_to_zero::check(cx, expr, count_arg, default_arg, span);
                 },
+                ("seek", [arg]) => {
+                    if meets_msrv(self.msrv, msrvs::SEEK_FROM_CURRENT) {
+                        seek_from_current::check(cx, expr, recv, arg);
+                    }
+                    if meets_msrv(self.msrv, msrvs::SEEK_REWIND) {
+                        seek_to_start_instead_of_rewind::check(cx, expr, recv, arg, span);
+                    }
+                },
                 ("sort", []) => {
                     stable_sort_primitive::check(cx, expr, recv);
                 },
@@ -3626,7 +3709,7 @@ impl Methods {
                 },
                 ("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg),
                 ("take", [_arg]) => {
-                    if let Some((name2, recv2, args2, _span2)) = method_call(recv) {
+                    if let Some((name2, recv2, args2, _span2, _)) = method_call(recv) {
                         if let ("cloned", []) = (name2, args2) {
                             iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
                         }
@@ -3649,13 +3732,13 @@ impl Methods {
                 },
                 ("unwrap", []) => {
                     match method_call(recv) {
-                        Some(("get", recv, [get_arg], _)) => {
+                        Some(("get", recv, [get_arg], _, _)) => {
                             get_unwrap::check(cx, expr, recv, get_arg, false);
                         },
-                        Some(("get_mut", recv, [get_arg], _)) => {
+                        Some(("get_mut", recv, [get_arg], _, _)) => {
                             get_unwrap::check(cx, expr, recv, get_arg, true);
                         },
-                        Some(("or", recv, [or_arg], or_span)) => {
+                        Some(("or", recv, [or_arg], or_span, _)) => {
                             or_then_unwrap::check(cx, expr, recv, or_arg, or_span);
                         },
                         _ => {},
@@ -3664,19 +3747,19 @@ impl Methods {
                 },
                 ("unwrap_err", []) => unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests),
                 ("unwrap_or", [u_arg]) => match method_call(recv) {
-                    Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), lhs, [rhs], _)) => {
+                    Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), lhs, [rhs], _, _)) => {
                         manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]);
                     },
-                    Some(("map", m_recv, [m_arg], span)) => {
+                    Some(("map", m_recv, [m_arg], span, _)) => {
                         option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span);
                     },
-                    Some(("then_some", t_recv, [t_arg], _)) => {
+                    Some(("then_some", t_recv, [t_arg], _, _)) => {
                         obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg);
                     },
                     _ => {},
                 },
                 ("unwrap_or_else", [u_arg]) => match method_call(recv) {
-                    Some(("map", recv, [map_arg], _))
+                    Some(("map", recv, [map_arg], _, _))
                         if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, self.msrv) => {},
                     _ => {
                         unwrap_or_else_default::check(cx, expr, recv, u_arg);
@@ -3697,7 +3780,7 @@ impl Methods {
 }
 
 fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, is_some: bool) {
-    if let Some((name @ ("find" | "position" | "rposition"), f_recv, [arg], span)) = method_call(recv) {
+    if let Some((name @ ("find" | "position" | "rposition"), f_recv, [arg], span, _)) = method_call(recv) {
         search_is_some::check(cx, expr, name, is_some, f_recv, arg, recv, span);
     }
 }
@@ -3906,14 +3989,6 @@ impl OutType {
     }
 }
 
-fn is_bool(ty: &hir::Ty<'_>) -> bool {
-    if let hir::TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
-        matches!(path.res, Res::PrimTy(PrimTy::Bool))
-    } else {
-        false
-    }
-}
-
 fn fn_header_equals(expected: hir::FnHeader, actual: hir::FnHeader) -> bool {
     expected.constness == actual.constness
         && expected.unsafety == actual.unsafety
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index 66f9e28596e..b088e642e0e 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -3,94 +3,99 @@ 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;
-use clippy_utils::{can_move_expr_to_closure, is_trait_method, path_to_local, path_to_local_id, CaptureKind};
-use if_chain::if_chain;
+use clippy_utils::ty::{is_type_diagnostic_item, make_normalized_projection, make_projection};
+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 rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
-use rustc_hir::{Block, Expr, ExprKind, HirId, HirIdSet, Local, Mutability, Node, PatKind, Stmt, StmtKind};
+use rustc_hir::{
+    BindingAnnotation, Block, Expr, ExprKind, HirId, HirIdSet, Local, Mutability, Node, PatKind, Stmt, StmtKind,
+};
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, Ty};
-use rustc_span::sym;
-use rustc_span::Span;
+use rustc_middle::ty::{self, AssocKind, EarlyBinder, GenericArg, GenericArgKind, Ty};
+use rustc_span::symbol::Ident;
+use rustc_span::{sym, Span, Symbol};
 
 const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed";
 
-pub(super) fn check<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) {
-    check_needless_collect_direct_usage(expr, cx);
-    check_needless_collect_indirect_usage(expr, cx);
-}
-fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) {
-    if_chain! {
-        if let ExprKind::MethodCall(method, receiver, args, _) = expr.kind;
-        if let ExprKind::MethodCall(chain_method, ..) = receiver.kind;
-        if chain_method.ident.name == sym!(collect) && is_trait_method(cx, receiver, sym::Iterator);
-        then {
-            let ty = cx.typeck_results().expr_ty(receiver);
-            let mut applicability = Applicability::MaybeIncorrect;
-            let is_empty_sugg = "next().is_none()".to_string();
-            let method_name = method.ident.name.as_str();
-            let sugg = if is_type_diagnostic_item(cx, ty, sym::Vec) ||
-                        is_type_diagnostic_item(cx, ty, sym::VecDeque) ||
-                        is_type_diagnostic_item(cx, ty, sym::LinkedList) ||
-                        is_type_diagnostic_item(cx, ty, sym::BinaryHeap) {
-                match method_name {
-                    "len" => "count()".to_string(),
-                    "is_empty" => is_empty_sugg,
-                    "contains" => {
-                        let contains_arg = snippet_with_applicability(cx, args[0].span, "??", &mut applicability);
-                        let (arg, pred) = contains_arg
-                            .strip_prefix('&')
-                            .map_or(("&x", &*contains_arg), |s| ("x", s));
-                        format!("any(|{arg}| x == {pred})")
-                    }
-                    _ => return,
-                }
-            }
-            else if is_type_diagnostic_item(cx, ty, sym::BTreeMap) ||
-                is_type_diagnostic_item(cx, ty, sym::HashMap) {
-                match method_name {
-                    "is_empty" => is_empty_sugg,
-                    _ => return,
-                }
-            }
-            else {
-                return;
-            };
-            span_lint_and_sugg(
-                cx,
-                NEEDLESS_COLLECT,
-                chain_method.ident.span.with_hi(expr.span.hi()),
-                NEEDLESS_COLLECT_MSG,
-                "replace with",
-                sugg,
-                applicability,
-            );
-        }
-    }
-}
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    name_span: Span,
+    collect_expr: &'tcx Expr<'_>,
+    iter_expr: &'tcx Expr<'tcx>,
+    call_span: Span,
+) {
+    if let Some(parent) = get_parent_node(cx.tcx, collect_expr.hir_id) {
+        match parent {
+            Node::Expr(parent) => {
+                if let ExprKind::MethodCall(name, _, args @ ([] | [_]), _) = parent.kind {
+                    let mut app = Applicability::MachineApplicable;
+                    let name = name.ident.as_str();
+                    let collect_ty = cx.typeck_results().expr_ty(collect_expr);
 
-fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) {
-    if let ExprKind::Block(block, _) = expr.kind {
-        for stmt in block.stmts {
-            if_chain! {
-                if let StmtKind::Local(local) = stmt.kind;
-                if let PatKind::Binding(_, id, ..) = local.pat.kind;
-                if let Some(init_expr) = local.init;
-                if let ExprKind::MethodCall(method_name, iter_source, [], ..) = init_expr.kind;
-                if method_name.ident.name == sym!(collect) && is_trait_method(cx, init_expr, sym::Iterator);
-                let ty = cx.typeck_results().expr_ty(init_expr);
-                if is_type_diagnostic_item(cx, ty, sym::Vec) ||
-                    is_type_diagnostic_item(cx, ty, sym::VecDeque) ||
-                    is_type_diagnostic_item(cx, ty, sym::BinaryHeap) ||
-                    is_type_diagnostic_item(cx, ty, sym::LinkedList);
-                let iter_ty = cx.typeck_results().expr_ty(iter_source);
-                if let Some(iter_calls) = detect_iter_and_into_iters(block, id, cx, get_captured_ids(cx, iter_ty));
-                if let [iter_call] = &*iter_calls;
-                then {
+                    let sugg: String = match name {
+                        "len" => {
+                            if let Some(adt) = collect_ty.ty_adt_def()
+                                && matches!(
+                                    cx.tcx.get_diagnostic_name(adt.did()),
+                                    Some(sym::Vec | sym::VecDeque | sym::LinkedList | sym::BinaryHeap)
+                                )
+                            {
+                                "count()".into()
+                            } else {
+                                return;
+                            }
+                        },
+                        "is_empty"
+                            if is_is_empty_sig(cx, parent.hir_id)
+                                && iterates_same_ty(cx, cx.typeck_results().expr_ty(iter_expr), collect_ty) =>
+                        {
+                            "next().is_none()".into()
+                        },
+                        "contains" => {
+                            if is_contains_sig(cx, parent.hir_id, iter_expr)
+                                && let Some(arg) = args.first()
+                            {
+                                let (span, prefix) = if let ExprKind::AddrOf(_, _, arg) = arg.kind {
+                                    (arg.span, "")
+                                } else {
+                                    (arg.span, "*")
+                                };
+                                let snip = snippet_with_applicability(cx, span, "??", &mut app);
+                                format!("any(|x| x == {prefix}{snip})")
+                            } else {
+                                return;
+                            }
+                        },
+                        _ => return,
+                    };
+
+                    span_lint_and_sugg(
+                        cx,
+                        NEEDLESS_COLLECT,
+                        call_span.with_hi(parent.span.hi()),
+                        NEEDLESS_COLLECT_MSG,
+                        "replace with",
+                        sugg,
+                        app,
+                    );
+                }
+            },
+            Node::Local(l) => {
+                if let PatKind::Binding(BindingAnnotation::NONE | BindingAnnotation::MUT, id, _, None)
+                    = l.pat.kind
+                    && let ty = cx.typeck_results().expr_ty(collect_expr)
+                    && [sym::Vec, sym::VecDeque, sym::BinaryHeap, sym::LinkedList].into_iter()
+                        .any(|item| is_type_diagnostic_item(cx, ty, item))
+                    && let iter_ty = cx.typeck_results().expr_ty(iter_expr)
+                    && let Some(block) = get_enclosing_block(cx, l.hir_id)
+                    && let Some(iter_calls) = detect_iter_and_into_iters(block, id, cx, get_captured_ids(cx, iter_ty))
+                    && let [iter_call] = &*iter_calls
+                {
                     let mut used_count_visitor = UsedCountVisitor {
                         cx,
                         id,
@@ -102,20 +107,20 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
                     }
 
                     // Suggest replacing iter_call with iter_replacement, and removing stmt
-                    let mut span = MultiSpan::from_span(method_name.ident.span);
+                    let mut span = MultiSpan::from_span(name_span);
                     span.push_span_label(iter_call.span, "the iterator could be used here instead");
                     span_lint_hir_and_then(
                         cx,
                         super::NEEDLESS_COLLECT,
-                        init_expr.hir_id,
+                        collect_expr.hir_id,
                         span,
                         NEEDLESS_COLLECT_MSG,
                         |diag| {
-                            let iter_replacement = format!("{}{}", Sugg::hir(cx, iter_source, ".."), iter_call.get_iter_method(cx));
+                            let iter_replacement = format!("{}{}", Sugg::hir(cx, iter_expr, ".."), iter_call.get_iter_method(cx));
                             diag.multipart_suggestion(
                                 iter_call.get_suggestion_text(),
                                 vec![
-                                    (stmt.span, String::new()),
+                                    (l.span, String::new()),
                                     (iter_call.span, iter_replacement)
                                 ],
                                 Applicability::MaybeIncorrect,
@@ -123,11 +128,61 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
                         },
                     );
                 }
-            }
+            },
+            _ => (),
         }
     }
 }
 
+/// 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| {
+        let sig = cx.tcx.fn_sig(id).skip_binder();
+        sig.inputs().len() == 1 && sig.output().is_bool()
+    })
+}
+
+/// Checks if `<iter_ty as Iterator>::Item` is the same as `<collect_ty as IntoIter>::Item`
+fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty: Ty<'tcx>) -> bool {
+    let item = Symbol::intern("Item");
+    if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator)
+        && let Some(into_iter_trait) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
+        && let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.param_env, iter_trait, item, [iter_ty])
+        && let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, item, [collect_ty])
+        && let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions(
+            cx.param_env,
+            cx.tcx.mk_projection(into_iter_item_proj.item_def_id, into_iter_item_proj.substs)
+        )
+    {
+        iter_item_ty == into_iter_item_ty
+    } else {
+        false
+    }
+}
+
+/// Checks if the given method call matches the expected signature of
+/// `([&[mut]] self, &<iter_ty as Iterator>::Item) -> bool`
+fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) -> bool {
+    let typeck = cx.typeck_results();
+    if let Some(id) = typeck.type_dependent_def_id(call_id)
+        && let sig = cx.tcx.fn_sig(id)
+        && sig.skip_binder().output().is_bool()
+        && let [_, search_ty] = *sig.skip_binder().inputs()
+        && let ty::Ref(_, search_ty, Mutability::Not) = *cx.tcx.erase_late_bound_regions(sig.rebind(search_ty)).kind()
+        && let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator)
+        && let Some(iter_item) = cx.tcx
+            .associated_items(iter_trait)
+            .find_by_name_and_kind(cx.tcx, Ident::with_dummy_span(Symbol::intern("Item")), AssocKind::Type, iter_trait)
+        && let substs = cx.tcx.mk_substs([GenericArg::from(typeck.expr_ty_adjusted(iter_expr))].into_iter())
+        && let proj_ty = cx.tcx.mk_projection(iter_item.def_id, substs)
+        && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty)
+    {
+        item_ty == EarlyBinder(search_ty).subst(cx.tcx, cx.typeck_results().node_substs(call_id))
+    } else {
+        false
+    }
+}
+
 struct IterFunction {
     func: IterFunctionKind,
     span: Span,
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
index 742483e6b2e..e6eb64bcbde 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -13,8 +13,8 @@ use rustc_span::sym;
 use super::OPTION_AS_REF_DEREF;
 
 /// lint use of `_.as_ref().map(Deref::deref)` for `Option`s
-pub(super) fn check<'tcx>(
-    cx: &LateContext<'tcx>,
+pub(super) fn check(
+    cx: &LateContext<'_>,
     expr: &hir::Expr<'_>,
     as_ref_recv: &hir::Expr<'_>,
     map_arg: &hir::Expr<'_>,
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
index 991d3dd538b..4460f38fcc1 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
@@ -83,6 +83,8 @@ pub(super) fn check<'tcx>(
         method_span: Span,
         self_expr: &hir::Expr<'_>,
         arg: &'tcx hir::Expr<'_>,
+        // `Some` if fn has second argument
+        second_arg: Option<&hir::Expr<'_>>,
         span: Span,
         // None if lambda is required
         fun_span: Option<Span>,
@@ -109,30 +111,40 @@ pub(super) fn check<'tcx>(
             if poss.contains(&name);
 
             then {
-                let macro_expanded_snipped;
-                let sugg: Cow<'_, str> = {
+                let sugg = {
                     let (snippet_span, use_lambda) = match (fn_has_arguments, fun_span) {
                         (false, Some(fun_span)) => (fun_span, false),
                         _ => (arg.span, true),
                     };
-                    let snippet = {
-                        let not_macro_argument_snippet = snippet_with_macro_callsite(cx, snippet_span, "..");
-                        if not_macro_argument_snippet == "vec![]" {
-                            macro_expanded_snipped = snippet(cx, snippet_span, "..");
+
+                    let format_span = |span: Span| {
+                        let not_macro_argument_snippet = snippet_with_macro_callsite(cx, span, "..");
+                        let snip = if not_macro_argument_snippet == "vec![]" {
+                            let macro_expanded_snipped = snippet(cx, snippet_span, "..");
                             match macro_expanded_snipped.strip_prefix("$crate::vec::") {
-                                Some(stripped) => Cow::from(stripped),
+                                Some(stripped) => Cow::Owned(stripped.to_owned()),
                                 None => macro_expanded_snipped,
                             }
                         } else {
                             not_macro_argument_snippet
-                        }
+                        };
+
+                        snip.to_string()
                     };
 
-                    if use_lambda {
+                    let snip = format_span(snippet_span);
+                    let snip = if use_lambda {
                         let l_arg = if fn_has_arguments { "_" } else { "" };
-                        format!("|{l_arg}| {snippet}").into()
+                        format!("|{l_arg}| {snip}")
                     } else {
-                        snippet
+                        snip
+                    };
+
+                    if let Some(f) = second_arg {
+                        let f = format_span(f.span);
+                        format!("{snip}, {f}")
+                    } else {
+                        snip
                     }
                 };
                 let span_replace_word = method_span.with_hi(span.hi());
@@ -149,8 +161,8 @@ pub(super) fn check<'tcx>(
         }
     }
 
-    if let [arg] = args {
-        let inner_arg = if let hir::ExprKind::Block(
+    let extract_inner_arg = |arg: &'tcx hir::Expr<'_>| {
+        if let hir::ExprKind::Block(
             hir::Block {
                 stmts: [],
                 expr: Some(expr),
@@ -162,19 +174,32 @@ pub(super) fn check<'tcx>(
             expr
         } else {
             arg
-        };
+        }
+    };
+
+    if let [arg] = args {
+        let inner_arg = extract_inner_arg(arg);
         match inner_arg.kind {
             hir::ExprKind::Call(fun, or_args) => {
                 let or_has_args = !or_args.is_empty();
                 if !check_unwrap_or_default(cx, name, fun, arg, or_has_args, expr.span, method_span) {
                     let fun_span = if or_has_args { None } else { Some(fun.span) };
-                    check_general_case(cx, name, method_span, receiver, arg, expr.span, fun_span);
+                    check_general_case(cx, name, method_span, receiver, arg, None, expr.span, fun_span);
                 }
             },
             hir::ExprKind::Index(..) | hir::ExprKind::MethodCall(..) => {
-                check_general_case(cx, name, method_span, receiver, arg, expr.span, None);
+                check_general_case(cx, name, method_span, receiver, arg, None, expr.span, None);
             },
             _ => (),
         }
     }
+
+    // `map_or` takes two arguments
+    if let [arg, lambda] = args {
+        let inner_arg = extract_inner_arg(arg);
+        if let hir::ExprKind::Call(fun, or_args) = inner_arg.kind {
+            let fun_span = if or_args.is_empty() { Some(fun.span) } else { None };
+            check_general_case(cx, name, method_span, receiver, arg, Some(lambda), expr.span, fun_span);
+        }
+    }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
new file mode 100644
index 00000000000..361a3082f94
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
@@ -0,0 +1,48 @@
+use rustc_ast::ast::{LitIntType, LitKind};
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::LateContext;
+
+use clippy_utils::{
+    diagnostics::span_lint_and_sugg, get_trait_def_id, match_def_path, paths, source::snippet_with_applicability,
+    ty::implements_trait,
+};
+
+use super::SEEK_FROM_CURRENT;
+
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) {
+    let ty = cx.typeck_results().expr_ty(recv);
+
+    if let Some(def_id) = get_trait_def_id(cx, &paths::STD_IO_SEEK) {
+        if implements_trait(cx, ty, def_id, &[]) && arg_is_seek_from_current(cx, arg) {
+            let mut applicability = Applicability::MachineApplicable;
+            let snip = snippet_with_applicability(cx, recv.span, "..", &mut applicability);
+
+            span_lint_and_sugg(
+                cx,
+                SEEK_FROM_CURRENT,
+                expr.span,
+                "using `SeekFrom::Current` to start from current position",
+                "replace with",
+                format!("{snip}.stream_position()"),
+                applicability,
+            );
+        }
+    }
+}
+
+fn arg_is_seek_from_current<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
+    if let ExprKind::Call(f, args) = expr.kind &&
+        let ExprKind::Path(ref path) = f.kind &&
+        let Some(def_id) = cx.qpath_res(path, f.hir_id).opt_def_id() &&
+        match_def_path(cx, def_id, &paths::STD_IO_SEEK_FROM_CURRENT) {
+        // check if argument of `SeekFrom::Current` is `0`
+        if args.len() == 1 &&
+            let ExprKind::Lit(ref lit) = args[0].kind &&
+            let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node {
+            return true
+        }
+    }
+
+    false
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
new file mode 100644
index 00000000000..7e3bed1e41a
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
@@ -0,0 +1,45 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::ty::implements_trait;
+use clippy_utils::{get_trait_def_id, match_def_path, paths};
+use rustc_ast::ast::{LitIntType, LitKind};
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::LateContext;
+use rustc_span::Span;
+
+use super::SEEK_TO_START_INSTEAD_OF_REWIND;
+
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'_>,
+    recv: &'tcx Expr<'_>,
+    arg: &'tcx Expr<'_>,
+    name_span: Span,
+) {
+    // Get receiver type
+    let ty = cx.typeck_results().expr_ty(recv).peel_refs();
+
+    if let Some(seek_trait_id) = get_trait_def_id(cx, &paths::STD_IO_SEEK) &&
+        implements_trait(cx, ty, seek_trait_id, &[]) &&
+        let ExprKind::Call(func, args1) = arg.kind &&
+        let ExprKind::Path(ref path) = func.kind &&
+        let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id() &&
+        match_def_path(cx, def_id, &paths::STD_IO_SEEKFROM_START) &&
+        args1.len() == 1 &&
+        let ExprKind::Lit(ref lit) = args1[0].kind &&
+        let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node
+    {
+        let method_call_span = expr.span.with_lo(name_span.lo());
+        span_lint_and_then(
+            cx,
+            SEEK_TO_START_INSTEAD_OF_REWIND,
+            method_call_span,
+            "used `seek` to go to the start of the stream",
+            |diag| {
+                let app = Applicability::MachineApplicable;
+
+                diag.span_suggestion(method_call_span, "replace with", "rewind()", app);
+            },
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs b/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs
index 6f4cec546e9..f35d81cee8e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs
@@ -18,7 +18,11 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
         let target = &arglists[0].0;
         let self_ty = cx.typeck_results().expr_ty(target).peel_refs();
         let ref_str = if *self_ty.kind() == ty::Str {
-            ""
+            if matches!(target.kind, hir::ExprKind::Index(..)) {
+                "&"
+            } else {
+                ""
+            }
         } else if is_type_lang_item(cx, self_ty, hir::LangItem::String) {
             "&"
         } else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs
index 851cdf54455..2ac0786b37b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs
@@ -8,7 +8,7 @@ use rustc_span::sym;
 
 use super::SUSPICIOUS_MAP;
 
-pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, count_recv: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) {
+pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, count_recv: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) {
     if_chain! {
         if is_trait_method(cx, count_recv, sym::Iterator);
         let closure = expr_or_init(cx, map_arg);
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
index 4eb579af7a1..52a4ff7d1ae 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -2,7 +2,7 @@ use super::utils::clone_or_copy_needed;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::ForLoop;
 use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait};
+use clippy_utils::ty::{get_iterator_item_ty, implements_trait};
 use clippy_utils::{fn_def_id, get_parent_expr};
 use rustc_errors::Applicability;
 use rustc_hir::{def_id::DefId, Expr, ExprKind};
@@ -54,7 +54,7 @@ pub fn check_for_loop_iter(
                 if let Some(into_iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator);
                 let collection_ty = cx.typeck_results().expr_ty(collection);
                 if implements_trait(cx, collection_ty, into_iterator_trait_id, &[]);
-                if let Some(into_iter_item_ty) = get_associated_type(cx, collection_ty, into_iterator_trait_id, "Item");
+                if let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, "Item");
 
                 if iter_item_ty == into_iter_item_ty;
                 if let Some(collection_snippet) = snippet_opt(cx, collection.span);
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs
index c9b87bc6bf2..087e1e4343b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs
@@ -31,7 +31,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 UNNECESSARY_JOIN,
                 span.with_hi(expr.span.hi()),
-                r#"called `.collect<Vec<String>>().join("")` on an iterator"#,
+                r#"called `.collect::<Vec<String>>().join("")` on an iterator"#,
                 "try using",
                 "collect::<String>()".to_owned(),
                 applicability,
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 375ebc903b4..8b000cd754c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -2,9 +2,11 @@ use super::implicit_clone::is_clone_like;
 use super::unnecessary_iter_cloned::{self, is_into_iter};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs};
+use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs};
 use clippy_utils::visitors::find_all_ret_expressions;
-use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty};
+use clippy_utils::{
+    fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty,
+};
 use clippy_utils::{meets_msrv, msrvs};
 use rustc_errors::Applicability;
 use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, Node};
@@ -18,7 +20,9 @@ use rustc_middle::ty::EarlyBinder;
 use rustc_middle::ty::{self, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty};
 use rustc_semver::RustcVersion;
 use rustc_span::{sym, Symbol};
-use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause};
+use rustc_trait_selection::traits::{
+    query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause,
+};
 use std::cmp::max;
 
 use super::UNNECESSARY_TO_OWNED;
@@ -146,7 +150,7 @@ fn check_addr_of_expr(
             if_chain! {
                 if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref);
                 if implements_trait(cx, receiver_ty, deref_trait_id, &[]);
-                if get_associated_type(cx, receiver_ty, deref_trait_id, "Target") == Some(target_ty);
+                if cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty);
                 then {
                     if n_receiver_refs > 0 {
                         span_lint_and_sugg(
@@ -341,13 +345,13 @@ fn get_input_traits_and_projections<'tcx>(
                 if trait_predicate.trait_ref.self_ty() == input {
                     trait_predicates.push(trait_predicate);
                 }
-            },
+            }
             PredicateKind::Projection(projection_predicate) => {
                 if projection_predicate.projection_ty.self_ty() == input {
                     projection_predicates.push(projection_predicate);
                 }
-            },
-            _ => {},
+            }
+            _ => {}
         }
     }
     (trait_predicates, projection_predicates)
@@ -462,7 +466,12 @@ fn is_cloned_or_copied(cx: &LateContext<'_>, method_name: Symbol, method_def_id:
 
 /// Returns true if the named method can be used to convert the receiver to its "owned"
 /// representation.
-fn is_to_owned_like<'a>(cx: &LateContext<'a>, call_expr: &Expr<'a>, method_name: Symbol, method_def_id: DefId) -> bool {
+fn is_to_owned_like<'a>(
+    cx: &LateContext<'a>,
+    call_expr: &Expr<'a>,
+    method_name: Symbol,
+    method_def_id: DefId,
+) -> bool {
     is_clone_like(cx, method_name.as_str(), method_def_id)
         || is_cow_into_owned(cx, method_name, method_def_id)
         || is_to_string_on_string_like(cx, call_expr, method_name, method_def_id)
@@ -490,7 +499,7 @@ fn is_to_string_on_string_like<'a>(
         && let GenericArgKind::Type(ty) = generic_arg.unpack()
         && let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref)
         && let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef)
-        && (get_associated_type(cx, ty, deref_trait_id, "Target") == Some(cx.tcx.types.str_) ||
+        && (cx.get_associated_type(ty, deref_trait_id, "Target") == Some(cx.tcx.types.str_) ||
             implements_trait(cx, ty, as_ref_trait_id, &[cx.tcx.types.str_.into()])) {
             true
         } else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs b/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs
index ee17f2d7889..90983f249cd 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_in_test_function, is_lint_allowed};
+use clippy_utils::{is_in_cfg_test, is_lint_allowed};
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_span::sym;
@@ -18,16 +18,16 @@ pub(super) fn check(
     let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs();
 
     let mess = if is_type_diagnostic_item(cx, obj_ty, sym::Option) && !is_err {
-        Some((UNWRAP_USED, "an Option", "None", ""))
+        Some((UNWRAP_USED, "an `Option`", "None", ""))
     } else if is_type_diagnostic_item(cx, obj_ty, sym::Result) {
-        Some((UNWRAP_USED, "a Result", if is_err { "Ok" } else { "Err" }, "an "))
+        Some((UNWRAP_USED, "a `Result`", if is_err { "Ok" } else { "Err" }, "an "))
     } else {
         None
     };
 
     let method_suffix = if is_err { "_err" } else { "" };
 
-    if allow_unwrap_in_tests && is_in_test_function(cx.tcx, expr.hir_id) {
+    if allow_unwrap_in_tests && is_in_cfg_test(cx.tcx, expr.hir_id) {
         return;
     }
 
@@ -45,7 +45,7 @@ pub(super) fn check(
             cx,
             lint,
             expr.span,
-            &format!("used `unwrap{method_suffix}()` on `{kind}` value"),
+            &format!("used `unwrap{method_suffix}()` on {kind} value"),
             None,
             &help,
         );
diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
index 872679f25ab..4712846939e 100644
--- a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
@@ -59,7 +59,7 @@ impl LateLintPass<'_> for ImportRename {
     fn check_crate(&mut self, cx: &LateContext<'_>) {
         for Rename { path, rename } in &self.conf_renames {
             let segs = path.split("::").collect::<Vec<_>>();
-            if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, None) {
+            for id in clippy_utils::def_path_def_ids(cx, &segs) {
                 self.renames.insert(id, Symbol::intern(rename));
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
index 6752976348f..321fa4b7f99 100644
--- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -218,7 +218,7 @@ enum StopEarly {
     Stop,
 }
 
-fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr<'_>) -> StopEarly {
+fn check_expr<'tcx>(vis: &mut ReadVisitor<'_, 'tcx>, expr: &'tcx Expr<'_>) -> StopEarly {
     if expr.hir_id == vis.last_expr.hir_id {
         return StopEarly::KeepGoing;
     }
@@ -265,7 +265,7 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr<'_>) -
     StopEarly::KeepGoing
 }
 
-fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt<'_>) -> StopEarly {
+fn check_stmt<'tcx>(vis: &mut ReadVisitor<'_, 'tcx>, stmt: &'tcx Stmt<'_>) -> StopEarly {
     match stmt.kind {
         StmtKind::Expr(expr) | StmtKind::Semi(expr) => check_expr(vis, expr),
         // If the declaration is of a local variable, check its initializer
diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs
index 4b62dcdffe2..a651020ca65 100644
--- a/src/tools/clippy/clippy_lints/src/mut_key.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_key.rs
@@ -1,10 +1,11 @@
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::trait_ref_of_method;
+use clippy_utils::{def_path_def_ids, trait_ref_of_method};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::TypeVisitable;
 use rustc_middle::ty::{Adt, Array, Ref, Slice, Tuple, Ty};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::sym;
 use std::iter;
@@ -78,26 +79,44 @@ declare_clippy_lint! {
     "Check for mutable `Map`/`Set` key type"
 }
 
-declare_lint_pass!(MutableKeyType => [ MUTABLE_KEY_TYPE ]);
+#[derive(Clone)]
+pub struct MutableKeyType {
+    ignore_interior_mutability: Vec<String>,
+    ignore_mut_def_ids: FxHashSet<hir::def_id::DefId>,
+}
+
+impl_lint_pass!(MutableKeyType => [ MUTABLE_KEY_TYPE ]);
 
 impl<'tcx> LateLintPass<'tcx> for MutableKeyType {
+    fn check_crate(&mut self, cx: &LateContext<'tcx>) {
+        self.ignore_mut_def_ids.clear();
+        let mut path = Vec::new();
+        for ty in &self.ignore_interior_mutability {
+            path.extend(ty.split("::"));
+            for id in def_path_def_ids(cx, &path[..]) {
+                self.ignore_mut_def_ids.insert(id);
+            }
+            path.clear();
+        }
+    }
+
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
         if let hir::ItemKind::Fn(ref sig, ..) = item.kind {
-            check_sig(cx, item.hir_id(), sig.decl);
+            self.check_sig(cx, item.hir_id(), sig.decl);
         }
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'tcx>) {
         if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind {
             if trait_ref_of_method(cx, item.owner_id.def_id).is_none() {
-                check_sig(cx, item.hir_id(), sig.decl);
+                self.check_sig(cx, item.hir_id(), sig.decl);
             }
         }
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'tcx>) {
         if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
-            check_sig(cx, item.hir_id(), sig.decl);
+            self.check_sig(cx, item.hir_id(), sig.decl);
         }
     }
 
@@ -105,73 +124,81 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType {
         if let hir::PatKind::Wild = local.pat.kind {
             return;
         }
-        check_ty(cx, local.span, cx.typeck_results().pat_ty(local.pat));
+        self.check_ty_(cx, local.span, cx.typeck_results().pat_ty(local.pat));
     }
 }
 
-fn check_sig<'tcx>(cx: &LateContext<'tcx>, item_hir_id: hir::HirId, decl: &hir::FnDecl<'_>) {
-    let fn_def_id = cx.tcx.hir().local_def_id(item_hir_id);
-    let fn_sig = cx.tcx.fn_sig(fn_def_id);
-    for (hir_ty, ty) in iter::zip(decl.inputs, fn_sig.inputs().skip_binder()) {
-        check_ty(cx, hir_ty.span, *ty);
+impl MutableKeyType {
+    pub fn new(ignore_interior_mutability: Vec<String>) -> Self {
+        Self {
+            ignore_interior_mutability,
+            ignore_mut_def_ids: FxHashSet::default(),
+        }
     }
-    check_ty(cx, decl.output.span(), cx.tcx.erase_late_bound_regions(fn_sig.output()));
-}
 
-// We want to lint 1. sets or maps with 2. not immutable key types and 3. no unerased
-// generics (because the compiler cannot ensure immutability for unknown types).
-fn check_ty<'tcx>(cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) {
-    let ty = ty.peel_refs();
-    if let Adt(def, substs) = ty.kind() {
-        let is_keyed_type = [sym::HashMap, sym::BTreeMap, sym::HashSet, sym::BTreeSet]
-            .iter()
-            .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did()));
-        if is_keyed_type && is_interior_mutable_type(cx, substs.type_at(0), span) {
-            span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type");
+    fn check_sig(&self, cx: &LateContext<'_>, item_hir_id: hir::HirId, decl: &hir::FnDecl<'_>) {
+        let fn_def_id = cx.tcx.hir().local_def_id(item_hir_id);
+        let fn_sig = cx.tcx.fn_sig(fn_def_id);
+        for (hir_ty, ty) in iter::zip(decl.inputs, fn_sig.inputs().skip_binder()) {
+            self.check_ty_(cx, hir_ty.span, *ty);
         }
+        self.check_ty_(cx, decl.output.span(), cx.tcx.erase_late_bound_regions(fn_sig.output()));
     }
-}
 
-/// Determines if a type contains interior mutability which would affect its implementation of
-/// [`Hash`] or [`Ord`].
-fn is_interior_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) -> bool {
-    match *ty.kind() {
-        Ref(_, inner_ty, mutbl) => {
-            mutbl == hir::Mutability::Mut || is_interior_mutable_type(cx, inner_ty, span)
-        }
-        Slice(inner_ty) => is_interior_mutable_type(cx, inner_ty, span),
-        Array(inner_ty, size) => {
-            size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0)
-                && is_interior_mutable_type(cx, inner_ty, span)
-        }
-        Tuple(fields) => fields.iter().any(|ty| is_interior_mutable_type(cx, ty, span)),
-        Adt(def, substs) => {
-            // Special case for collections in `std` who's impl of `Hash` or `Ord` delegates to
-            // that of their type parameters.  Note: we don't include `HashSet` and `HashMap`
-            // because they have no impl for `Hash` or `Ord`.
-            let is_std_collection = [
-                sym::Option,
-                sym::Result,
-                sym::LinkedList,
-                sym::Vec,
-                sym::VecDeque,
-                sym::BTreeMap,
-                sym::BTreeSet,
-                sym::Rc,
-                sym::Arc,
-            ]
-            .iter()
-            .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did()));
-            let is_box = Some(def.did()) == cx.tcx.lang_items().owned_box();
-            if is_std_collection || is_box {
-                // The type is mutable if any of its type parameters are
-                substs.types().any(|ty| is_interior_mutable_type(cx, ty, span))
-            } else {
-                !ty.has_escaping_bound_vars()
-                    && cx.tcx.layout_of(cx.param_env.and(ty)).is_ok()
-                    && !ty.is_freeze(cx.tcx, cx.param_env)
+    // We want to lint 1. sets or maps with 2. not immutable key types and 3. no unerased
+    // generics (because the compiler cannot ensure immutability for unknown types).
+    fn check_ty_<'tcx>(&self, cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) {
+        let ty = ty.peel_refs();
+        if let Adt(def, substs) = ty.kind() {
+            let is_keyed_type = [sym::HashMap, sym::BTreeMap, sym::HashSet, sym::BTreeSet]
+                .iter()
+                .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did()));
+            if is_keyed_type && self.is_interior_mutable_type(cx, substs.type_at(0)) {
+                span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type");
             }
         }
-        _ => false,
+    }
+
+    /// Determines if a type contains interior mutability which would affect its implementation of
+    /// [`Hash`] or [`Ord`].
+    fn is_interior_mutable_type<'tcx>(&self, cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+        match *ty.kind() {
+            Ref(_, inner_ty, mutbl) => mutbl == hir::Mutability::Mut || self.is_interior_mutable_type(cx, inner_ty),
+            Slice(inner_ty) => self.is_interior_mutable_type(cx, inner_ty),
+            Array(inner_ty, size) => {
+                size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0)
+                    && self.is_interior_mutable_type(cx, inner_ty)
+            },
+            Tuple(fields) => fields.iter().any(|ty| self.is_interior_mutable_type(cx, ty)),
+            Adt(def, substs) => {
+                // Special case for collections in `std` who's impl of `Hash` or `Ord` delegates to
+                // that of their type parameters.  Note: we don't include `HashSet` and `HashMap`
+                // because they have no impl for `Hash` or `Ord`.
+                let def_id = def.did();
+                let is_std_collection = [
+                    sym::Option,
+                    sym::Result,
+                    sym::LinkedList,
+                    sym::Vec,
+                    sym::VecDeque,
+                    sym::BTreeMap,
+                    sym::BTreeSet,
+                    sym::Rc,
+                    sym::Arc,
+                ]
+                .iter()
+                .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def_id));
+                let is_box = Some(def_id) == cx.tcx.lang_items().owned_box();
+                if is_std_collection || is_box || self.ignore_mut_def_ids.contains(&def_id) {
+                    // The type is mutable if any of its type parameters are
+                    substs.types().any(|ty| self.is_interior_mutable_type(cx, ty))
+                } else {
+                    !ty.has_escaping_bound_vars()
+                        && cx.tcx.layout_of(cx.param_env.and(ty)).is_ok()
+                        && !ty.is_freeze(cx.tcx, cx.param_env)
+                }
+            },
+            _ => false,
+        }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs
index cb16f00047a..bc90e131b7f 100644
--- a/src/tools/clippy/clippy_lints/src/mut_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs
@@ -68,13 +68,15 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
                     expr.span,
                     "generally you want to avoid `&mut &mut _` if possible",
                 );
-            } else if let ty::Ref(_, _, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind() {
-                span_lint(
-                    self.cx,
-                    MUT_MUT,
-                    expr.span,
-                    "this expression mutably borrows a mutable reference. Consider reborrowing",
-                );
+            } else if let ty::Ref(_, ty, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind() {
+                if ty.peel_refs().is_sized(self.cx.tcx, self.cx.param_env) {
+                    span_lint(
+                        self.cx,
+                        MUT_MUT,
+                        expr.span,
+                        "this expression mutably borrows a mutable reference. Consider reborrowing",
+                    );
+                }
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs b/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs
index 10c3ff026b6..498e1408e52 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs
@@ -36,14 +36,14 @@ declare_clippy_lint! {
 declare_lint_pass!(NeedlessBorrowedRef => [NEEDLESS_BORROWED_REFERENCE]);
 
 impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
-    fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
-        if pat.span.from_expansion() {
+    fn check_pat(&mut self, cx: &LateContext<'tcx>, ref_pat: &'tcx Pat<'_>) {
+        if ref_pat.span.from_expansion() {
             // OK, simple enough, lints doesn't check in macro.
             return;
         }
 
         // Do not lint patterns that are part of an OR `|` pattern, the binding mode must match in all arms
-        for (_, node) in cx.tcx.hir().parent_iter(pat.hir_id) {
+        for (_, node) in cx.tcx.hir().parent_iter(ref_pat.hir_id) {
             let Node::Pat(pat) = node else { break };
 
             if matches!(pat.kind, PatKind::Or(_)) {
@@ -52,20 +52,20 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
         }
 
         // Only lint immutable refs, because `&mut ref T` may be useful.
-        let PatKind::Ref(sub_pat, Mutability::Not) = pat.kind else { return };
+        let PatKind::Ref(pat, Mutability::Not) = ref_pat.kind else { return };
 
-        match sub_pat.kind {
+        match pat.kind {
             // Check sub_pat got a `ref` keyword (excluding `ref mut`).
             PatKind::Binding(BindingAnnotation::REF, _, ident, None) => {
                 span_lint_and_then(
                     cx,
                     NEEDLESS_BORROWED_REFERENCE,
-                    pat.span,
+                    ref_pat.span,
                     "this pattern takes a reference on something that is being dereferenced",
                     |diag| {
                         // `&ref ident`
                         //  ^^^^^
-                        let span = pat.span.until(ident.span);
+                        let span = ref_pat.span.until(ident.span);
                         diag.span_suggestion_verbose(
                             span,
                             "try removing the `&ref` part",
@@ -84,41 +84,71 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
                 }),
                 after,
             ) => {
-                let mut suggestions = Vec::new();
-
-                for element_pat in itertools::chain(before, after) {
-                    if let PatKind::Binding(BindingAnnotation::REF, _, ident, None) = element_pat.kind {
-                        // `&[..., ref ident, ...]`
-                        //         ^^^^
-                        let span = element_pat.span.until(ident.span);
-                        suggestions.push((span, String::new()));
-                    } else {
-                        return;
-                    }
-                }
+                check_subpatterns(
+                    cx,
+                    "dereferencing a slice pattern where every element takes a reference",
+                    ref_pat,
+                    pat,
+                    itertools::chain(before, after),
+                );
+            },
+            PatKind::Tuple(subpatterns, _) | PatKind::TupleStruct(_, subpatterns, _) => {
+                check_subpatterns(
+                    cx,
+                    "dereferencing a tuple pattern where every element takes a reference",
+                    ref_pat,
+                    pat,
+                    subpatterns,
+                );
+            },
+            PatKind::Struct(_, fields, _) => {
+                check_subpatterns(
+                    cx,
+                    "dereferencing a struct pattern where every field's pattern takes a reference",
+                    ref_pat,
+                    pat,
+                    fields.iter().map(|field| field.pat),
+                );
+            },
+            _ => {},
+        }
+    }
+}
 
-                if !suggestions.is_empty() {
-                    span_lint_and_then(
-                        cx,
-                        NEEDLESS_BORROWED_REFERENCE,
-                        pat.span,
-                        "dereferencing a slice pattern where every element takes a reference",
-                        |diag| {
-                            // `&[...]`
-                            //  ^
-                            let span = pat.span.until(sub_pat.span);
-                            suggestions.push((span, String::new()));
+fn check_subpatterns<'tcx>(
+    cx: &LateContext<'tcx>,
+    message: &str,
+    ref_pat: &Pat<'_>,
+    pat: &Pat<'_>,
+    subpatterns: impl IntoIterator<Item = &'tcx Pat<'tcx>>,
+) {
+    let mut suggestions = Vec::new();
 
-                            diag.multipart_suggestion(
-                                "try removing the `&` and `ref` parts",
-                                suggestions,
-                                Applicability::MachineApplicable,
-                            );
-                        },
-                    );
-                }
+    for subpattern in subpatterns {
+        match subpattern.kind {
+            PatKind::Binding(BindingAnnotation::REF, _, ident, None) => {
+                // `ref ident`
+                //  ^^^^
+                let span = subpattern.span.until(ident.span);
+                suggestions.push((span, String::new()));
             },
-            _ => {},
+            PatKind::Wild => {},
+            _ => return,
         }
     }
+
+    if !suggestions.is_empty() {
+        span_lint_and_then(cx, NEEDLESS_BORROWED_REFERENCE, ref_pat.span, message, |diag| {
+            // `&pat`
+            //  ^
+            let span = ref_pat.span.until(pat.span);
+            suggestions.push((span, String::new()));
+
+            diag.multipart_suggestion(
+                "try removing the `&` and `ref` parts",
+                suggestions,
+                Applicability::MachineApplicable,
+            );
+        });
+    }
 }
diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs
index 6f0e755466e..38a75034cd3 100644
--- a/src/tools/clippy/clippy_lints/src/needless_continue.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs
@@ -287,7 +287,7 @@ const DROP_ELSE_BLOCK_MSG: &str = "consider dropping the `else` clause";
 
 const DROP_CONTINUE_EXPRESSION_MSG: &str = "consider dropping the `continue` expression";
 
-fn emit_warning<'a>(cx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str, typ: LintType) {
+fn emit_warning(cx: &EarlyContext<'_>, data: &LintData<'_>, header: &str, typ: LintType) {
     // snip    is the whole *help* message that appears after the warning.
     // message is the warning message.
     // expr    is the expression which the lint warning message refers to.
@@ -313,7 +313,7 @@ fn emit_warning<'a>(cx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str,
     );
 }
 
-fn suggestion_snippet_for_continue_inside_if<'a>(cx: &EarlyContext<'_>, data: &'a LintData<'_>) -> String {
+fn suggestion_snippet_for_continue_inside_if(cx: &EarlyContext<'_>, data: &LintData<'_>) -> String {
     let cond_code = snippet(cx, data.if_cond.span, "..");
 
     let continue_code = snippet_block(cx, data.if_block.span, "..", Some(data.if_expr.span));
@@ -327,7 +327,7 @@ fn suggestion_snippet_for_continue_inside_if<'a>(cx: &EarlyContext<'_>, data: &'
     )
 }
 
-fn suggestion_snippet_for_continue_inside_else<'a>(cx: &EarlyContext<'_>, data: &'a LintData<'_>) -> String {
+fn suggestion_snippet_for_continue_inside_else(cx: &EarlyContext<'_>, data: &LintData<'_>) -> String {
     let cond_code = snippet(cx, data.if_cond.span, "..");
 
     // Region B
@@ -361,7 +361,7 @@ fn suggestion_snippet_for_continue_inside_else<'a>(cx: &EarlyContext<'_>, data:
     )
 }
 
-fn check_and_warn<'a>(cx: &EarlyContext<'_>, expr: &'a ast::Expr) {
+fn check_and_warn(cx: &EarlyContext<'_>, expr: &ast::Expr) {
     if_chain! {
         if let ast::ExprKind::Loop(loop_block, ..) = &expr.kind;
         if let Some(last_stmt) = loop_block.stmts.last();
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index eeff15bbfb4..55599cd03eb 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -340,11 +340,5 @@ impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt {
 
     fn mutate(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {}
 
-    fn fake_read(
-        &mut self,
-        _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>,
-        _: FakeReadCause,
-        _: HirId,
-    ) {
-    }
+    fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
 }
diff --git a/src/tools/clippy/clippy_lints/src/octal_escapes.rs b/src/tools/clippy/clippy_lints/src/octal_escapes.rs
index 2a7159764e4..ae0a41db918 100644
--- a/src/tools/clippy/clippy_lints/src/octal_escapes.rs
+++ b/src/tools/clippy/clippy_lints/src/octal_escapes.rs
@@ -58,9 +58,9 @@ impl EarlyLintPass for OctalEscapes {
 
         if let ExprKind::Lit(token_lit) = &expr.kind {
             if matches!(token_lit.kind, LitKind::Str) {
-                check_lit(cx, &token_lit, expr.span, true);
+                check_lit(cx, token_lit, expr.span, true);
             } else if matches!(token_lit.kind, LitKind::ByteStr) {
-                check_lit(cx, &token_lit, expr.span, false);
+                check_lit(cx, token_lit, expr.span, false);
             }
         }
     }
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 8827daaa3ee..20b82d81a2a 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
@@ -1,5 +1,9 @@
 use super::ARITHMETIC_SIDE_EFFECTS;
-use clippy_utils::{consts::constant_simple, diagnostics::span_lint};
+use clippy_utils::{
+    consts::{constant, constant_simple},
+    diagnostics::span_lint,
+    peel_hir_expr_refs,
+};
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
@@ -38,24 +42,6 @@ impl ArithmeticSideEffects {
         }
     }
 
-    /// Assuming that `expr` is a literal integer, checks operators (+=, -=, *, /) in a
-    /// non-constant environment that won't overflow.
-    fn has_valid_op(op: &Spanned<hir::BinOpKind>, expr: &hir::Expr<'_>) -> bool {
-        if let hir::ExprKind::Lit(ref lit) = expr.kind &&
-            let ast::LitKind::Int(value, _) = lit.node
-        {
-            match (&op.node, value) {
-                (hir::BinOpKind::Div | hir::BinOpKind::Rem, 0) => false,
-                (hir::BinOpKind::Add | hir::BinOpKind::Sub, 0)
-                    | (hir::BinOpKind::Div | hir::BinOpKind::Rem, _)
-                    | (hir::BinOpKind::Mul, 0 | 1) => true,
-                _ => false,
-            }
-        } else {
-            false
-        }
-    }
-
     /// Checks if the given `expr` has any of the inner `allowed` elements.
     fn is_allowed_ty(&self, ty: Ty<'_>) -> bool {
         self.allowed
@@ -74,15 +60,14 @@ impl ArithmeticSideEffects {
         self.expr_span = Some(expr.span);
     }
 
-    /// If `expr` does not match any variant of `LiteralIntegerTy`, returns `None`.
-    fn literal_integer<'expr, 'tcx>(expr: &'expr hir::Expr<'tcx>) -> Option<LiteralIntegerTy<'expr, 'tcx>> {
-        if matches!(expr.kind, hir::ExprKind::Lit(_)) {
-            return Some(LiteralIntegerTy::Value(expr));
+    /// If `expr` is not a literal integer like `1`, returns `None`.
+    fn literal_integer(expr: &hir::Expr<'_>) -> Option<u128> {
+        if let hir::ExprKind::Lit(ref lit) = expr.kind && let ast::LitKind::Int(n, _) = lit.node {
+            Some(n)
         }
-        if let hir::ExprKind::AddrOf(.., inn) = expr.kind && let hir::ExprKind::Lit(_) = inn.kind {
-            return Some(LiteralIntegerTy::Ref(inn));
+        else {
+            None
         }
-        None
     }
 
     /// Manages when the lint should be triggered. Operations in constant environments, hard coded
@@ -117,10 +102,20 @@ impl ArithmeticSideEffects {
             return;
         }
         let has_valid_op = if Self::is_integral(lhs_ty) && Self::is_integral(rhs_ty) {
-            match (Self::literal_integer(lhs), Self::literal_integer(rhs)) {
-                (None, Some(lit_int_ty)) | (Some(lit_int_ty), None) => Self::has_valid_op(op, lit_int_ty.into()),
-                (Some(LiteralIntegerTy::Value(_)), Some(LiteralIntegerTy::Value(_))) => true,
-                (None, None) | (Some(_), Some(_)) => false,
+            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(actual_lhs), Self::literal_integer(actual_rhs)) {
+                (None, None) => false,
+                (None, Some(n)) | (Some(n), None) => match (&op.node, n) {
+                    (hir::BinOpKind::Div | hir::BinOpKind::Rem, 0) => false,
+                    (hir::BinOpKind::Add | hir::BinOpKind::Sub, 0)
+                    | (hir::BinOpKind::Div | hir::BinOpKind::Rem, _)
+                    | (hir::BinOpKind::Mul, 0 | 1) => true,
+                    _ => false,
+                },
+                (Some(_), Some(_)) => {
+                    matches!((lhs_ref_counter, rhs_ref_counter), (0, 0))
+                },
             }
         } else {
             false
@@ -129,21 +124,45 @@ impl ArithmeticSideEffects {
             self.issue_lint(cx, expr);
         }
     }
+
+    fn manage_unary_ops<'tcx>(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        expr: &hir::Expr<'tcx>,
+        un_expr: &hir::Expr<'tcx>,
+        un_op: hir::UnOp,
+    ) {
+        let hir::UnOp::Neg = un_op else { return; };
+        if constant(cx, cx.typeck_results(), un_expr).is_some() {
+            return;
+        }
+        let ty = cx.typeck_results().expr_ty(expr).peel_refs();
+        if self.is_allowed_ty(ty) {
+            return;
+        }
+        let actual_un_expr = peel_hir_expr_refs(un_expr).0;
+        if Self::literal_integer(actual_un_expr).is_some() {
+            return;
+        }
+        self.issue_lint(cx, expr);
+    }
+
+    fn should_skip_expr(&mut self, expr: &hir::Expr<'_>) -> bool {
+        self.expr_span.is_some() || self.const_span.map_or(false, |sp| sp.contains(expr.span))
+    }
 }
 
 impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) {
-        if self.expr_span.is_some() || self.const_span.map_or(false, |sp| sp.contains(expr.span)) {
+        if self.should_skip_expr(expr) {
             return;
         }
         match &expr.kind {
-            hir::ExprKind::Binary(op, lhs, rhs) | hir::ExprKind::AssignOp(op, lhs, rhs) => {
+            hir::ExprKind::AssignOp(op, lhs, rhs) | hir::ExprKind::Binary(op, lhs, rhs) => {
                 self.manage_bin_ops(cx, expr, op, lhs, rhs);
             },
-            hir::ExprKind::Unary(hir::UnOp::Neg, _) => {
-                if constant_simple(cx, cx.typeck_results(), expr).is_none() {
-                    self.issue_lint(cx, expr);
-                }
+            hir::ExprKind::Unary(un_op, un_expr) => {
+                self.manage_unary_ops(cx, expr, un_expr, *un_op);
             },
             _ => {},
         }
@@ -177,22 +196,3 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
         }
     }
 }
-
-/// Tells if an expression is a integer declared by value or by reference.
-///
-/// If `LiteralIntegerTy::Ref`, then the contained value will be `hir::ExprKind::Lit` rather
-/// than `hirExprKind::Addr`.
-enum LiteralIntegerTy<'expr, 'tcx> {
-    /// For example, `&199`
-    Ref(&'expr hir::Expr<'tcx>),
-    /// For example, `1` or `i32::MAX`
-    Value(&'expr hir::Expr<'tcx>),
-}
-
-impl<'expr, 'tcx> From<LiteralIntegerTy<'expr, 'tcx>> for &'expr hir::Expr<'tcx> {
-    fn from(from: LiteralIntegerTy<'expr, 'tcx>) -> Self {
-        match from {
-            LiteralIntegerTy::Ref(elem) | LiteralIntegerTy::Value(elem) => elem,
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
index 71b31b5e4a5..d7917e86a86 100644
--- a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
@@ -199,7 +199,7 @@ fn in_impl<'tcx>(
     }
 }
 
-fn are_equal<'tcx>(cx: &LateContext<'tcx>, middle_ty: Ty<'_>, hir_ty: &rustc_hir::Ty<'_>) -> bool {
+fn are_equal(cx: &LateContext<'_>, middle_ty: Ty<'_>, hir_ty: &rustc_hir::Ty<'_>) -> bool {
     if_chain! {
         if let ty::Adt(adt_def, _) = middle_ty.kind();
         if let Some(local_did) = adt_def.did().as_local();
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 4eb42da1fed..472f52380bb 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
@@ -213,11 +213,14 @@ fn try_convert_match<'tcx>(
     cx: &LateContext<'tcx>,
     arms: &[Arm<'tcx>],
 ) -> Option<(&'tcx Pat<'tcx>, &'tcx Expr<'tcx>, &'tcx Expr<'tcx>)> {
-    if arms.len() == 2 {
-        return if is_none_or_err_arm(cx, &arms[1]) {
-            Some((arms[0].pat, arms[0].body, arms[1].body))
-        } else if is_none_or_err_arm(cx, &arms[0]) {
-            Some((arms[1].pat, arms[1].body, arms[0].body))
+    if let [first_arm, second_arm] = arms
+        && first_arm.guard.is_none()
+        && second_arm.guard.is_none()
+        {
+        return if is_none_or_err_arm(cx, second_arm) {
+            Some((first_arm.pat, first_arm.body, second_arm.body))
+        } else if is_none_or_err_arm(cx, first_arm) {
+            Some((second_arm.pat, second_arm.body, first_arm.body))
         } else {
             None
         };
diff --git a/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs b/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs
index 6810a243175..456ded3fc02 100644
--- a/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs
+++ b/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs
@@ -33,7 +33,7 @@ declare_clippy_lint! {
     ///     if f.is_some() { "yay" } else { "nay" }
     /// }
     /// ```
-    #[clippy::version = "1.64.0"]
+    #[clippy::version = "1.65.0"]
     pub PARTIALEQ_TO_NONE,
     style,
     "Binary comparison to `Option<T>::None` relies on `T: PartialEq`, which is unneeded"
diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
index a4d265111f9..97b5a4ce364 100644
--- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
@@ -130,7 +130,7 @@ enum DerefPossible {
     Impossible,
 }
 
-fn apply_lint<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'_>, deref_possible: DerefPossible) -> bool {
+fn apply_lint(cx: &LateContext<'_>, pat: &Pat<'_>, deref_possible: DerefPossible) -> bool {
     let maybe_mismatch = find_first_mismatch(cx, pat);
     if let Some((span, mutability, level)) = maybe_mismatch {
         span_lint_and_help(
@@ -163,7 +163,7 @@ enum Level {
     Lower,
 }
 
-fn find_first_mismatch<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'_>) -> Option<(Span, Mutability, Level)> {
+fn find_first_mismatch(cx: &LateContext<'_>, pat: &Pat<'_>) -> Option<(Span, Mutability, Level)> {
     let mut result = None;
     pat.walk(|p| {
         if result.is_some() {
diff --git a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
index 72dda67c72b..47b8891e123 100644
--- a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
@@ -105,17 +105,17 @@ fn expr_as_ptr_offset_call<'tcx>(
 }
 
 // Is the type of the expression a usize?
-fn is_expr_ty_usize<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool {
+fn is_expr_ty_usize(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     cx.typeck_results().expr_ty(expr) == cx.tcx.types.usize
 }
 
 // Is the type of the expression a raw pointer?
-fn is_expr_ty_raw_ptr<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool {
+fn is_expr_ty_raw_ptr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     cx.typeck_results().expr_ty(expr).is_unsafe_ptr()
 }
 
-fn build_suggestion<'tcx>(
-    cx: &LateContext<'tcx>,
+fn build_suggestion(
+    cx: &LateContext<'_>,
     method: Method,
     receiver_expr: &Expr<'_>,
     cast_lhs_expr: &Expr<'_>,
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index bb86fb3b7d4..5269bbd1f1a 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -189,6 +189,7 @@ fn is_early_return(smbl: Symbol, cx: &LateContext<'_>, if_block: &IfBlockType<'_
                             && expr_return_none_or_err(smbl, cx, if_else.unwrap(), let_expr, Some(let_pat_sym)))
                             || is_res_lang_ctor(cx, res, ResultErr)
                                 && expr_return_none_or_err(smbl, cx, if_then, let_expr, Some(let_pat_sym))
+                                && if_else.is_none()
                     },
                     _ => false,
                 }
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
index 4cbe9597c53..8e675d34a18 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -105,8 +105,8 @@ impl EarlyLintPass for RedundantClosureCall {
 
 impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
     fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
-        fn count_closure_usage<'a, 'tcx>(
-            cx: &'a LateContext<'tcx>,
+        fn count_closure_usage<'tcx>(
+            cx: &LateContext<'tcx>,
             block: &'tcx hir::Block<'_>,
             path: &'tcx hir::Path<'tcx>,
         ) -> usize {
diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
index 26075e9f70f..833dc4913b4 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
@@ -70,7 +70,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
         }
 
         if let ItemKind::Mod { .. } = item.kind {
-            self.is_exported.push(cx.effective_visibilities.is_exported(item.owner_id.def_id));
+            self.is_exported
+                .push(cx.effective_visibilities.is_exported(item.owner_id.def_id));
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
index 76d6ad0b23e..8e214218f23 100644
--- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
@@ -11,8 +11,6 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::disallowed_method", "clippy::disallowed_methods"),
     ("clippy::disallowed_type", "clippy::disallowed_types"),
     ("clippy::eval_order_dependence", "clippy::mixed_read_write_in_expression"),
-    ("clippy::for_loop_over_option", "for_loops_over_fallibles"),
-    ("clippy::for_loop_over_result", "for_loops_over_fallibles"),
     ("clippy::identity_conversion", "clippy::useless_conversion"),
     ("clippy::if_let_some_result", "clippy::match_result_ok"),
     ("clippy::logic_bug", "clippy::overly_complex_bool_expr"),
@@ -31,10 +29,13 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::to_string_in_display", "clippy::recursive_format_impl"),
     ("clippy::zero_width_space", "clippy::invisible_characters"),
     ("clippy::drop_bounds", "drop_bounds"),
+    ("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::into_iter_on_array", "array_into_iter"),
     ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
     ("clippy::invalid_ref", "invalid_value"),
+    ("clippy::let_underscore_drop", "let_underscore_drop"),
     ("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"),
     ("clippy::panic_params", "non_fmt_panics"),
     ("clippy::positional_named_format_parameters", "named_arguments_used_positionally"),
diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
index 66b79513032..2036e85db7e 100644
--- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
@@ -1,8 +1,9 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
+use rustc_ast::node_id::{NodeId, NodeMap};
 use rustc_ast::{ptr::P, Crate, Item, ItemKind, MacroDef, ModKind, UseTreeKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{edition::Edition, symbol::kw, Span, Symbol};
 
 declare_clippy_lint! {
@@ -33,51 +34,32 @@ declare_clippy_lint! {
     "imports with single component path are redundant"
 }
 
-declare_lint_pass!(SingleComponentPathImports => [SINGLE_COMPONENT_PATH_IMPORTS]);
+#[derive(Default)]
+pub struct SingleComponentPathImports {
+    /// Buffer found usages to emit when visiting that item so that `#[allow]` works as expected
+    found: NodeMap<Vec<SingleUse>>,
+}
+
+struct SingleUse {
+    name: Symbol,
+    span: Span,
+    item_id: NodeId,
+    can_suggest: bool,
+}
+
+impl_lint_pass!(SingleComponentPathImports => [SINGLE_COMPONENT_PATH_IMPORTS]);
 
 impl EarlyLintPass for SingleComponentPathImports {
     fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
         if cx.sess().opts.edition < Edition::Edition2018 {
             return;
         }
-        check_mod(cx, &krate.items);
-    }
-}
 
-fn check_mod(cx: &EarlyContext<'_>, items: &[P<Item>]) {
-    // keep track of imports reused with `self` keyword,
-    // such as `self::crypto_hash` in the example below
-    // ```rust,ignore
-    // use self::crypto_hash::{Algorithm, Hasher};
-    // ```
-    let mut imports_reused_with_self = Vec::new();
-
-    // keep track of single use statements
-    // such as `crypto_hash` in the example below
-    // ```rust,ignore
-    // use crypto_hash;
-    // ```
-    let mut single_use_usages = Vec::new();
-
-    // keep track of macros defined in the module as we don't want it to trigger on this (#7106)
-    // ```rust,ignore
-    // macro_rules! foo { () => {} };
-    // pub(crate) use foo;
-    // ```
-    let mut macros = Vec::new();
-
-    for item in items {
-        track_uses(
-            cx,
-            item,
-            &mut imports_reused_with_self,
-            &mut single_use_usages,
-            &mut macros,
-        );
+        self.check_mod(cx, &krate.items);
     }
 
-    for (name, span, can_suggest) in single_use_usages {
-        if !imports_reused_with_self.contains(&name) {
+    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
+        for SingleUse { span, can_suggest, .. } in self.found.remove(&item.id).into_iter().flatten() {
             if can_suggest {
                 span_lint_and_sugg(
                     cx,
@@ -102,74 +84,127 @@ fn check_mod(cx: &EarlyContext<'_>, items: &[P<Item>]) {
     }
 }
 
-fn track_uses(
-    cx: &EarlyContext<'_>,
-    item: &Item,
-    imports_reused_with_self: &mut Vec<Symbol>,
-    single_use_usages: &mut Vec<(Symbol, Span, bool)>,
-    macros: &mut Vec<Symbol>,
-) {
-    if item.span.from_expansion() || item.vis.kind.is_pub() {
-        return;
-    }
+impl SingleComponentPathImports {
+    fn check_mod(&mut self, cx: &EarlyContext<'_>, items: &[P<Item>]) {
+        // keep track of imports reused with `self` keyword, such as `self::crypto_hash` in the example
+        // below. Removing the `use crypto_hash;` would make this a compile error
+        // ```
+        // use crypto_hash;
+        //
+        // use self::crypto_hash::{Algorithm, Hasher};
+        // ```
+        let mut imports_reused_with_self = Vec::new();
 
-    match &item.kind {
-        ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) => {
-            check_mod(cx, items);
-        },
-        ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => {
-            macros.push(item.ident.name);
-        },
-        ItemKind::Use(use_tree) => {
-            let segments = &use_tree.prefix.segments;
-
-            // keep track of `use some_module;` usages
-            if segments.len() == 1 {
-                if let UseTreeKind::Simple(None, _, _) = use_tree.kind {
-                    let name = segments[0].ident.name;
-                    if !macros.contains(&name) {
-                        single_use_usages.push((name, item.span, true));
-                    }
-                }
-                return;
+        // keep track of single use statements such as `crypto_hash` in the example below
+        // ```
+        // use crypto_hash;
+        // ```
+        let mut single_use_usages = Vec::new();
+
+        // keep track of macros defined in the module as we don't want it to trigger on this (#7106)
+        // ```
+        // macro_rules! foo { () => {} };
+        // pub(crate) use foo;
+        // ```
+        let mut macros = Vec::new();
+
+        for item in items {
+            self.track_uses(
+                cx,
+                item,
+                &mut imports_reused_with_self,
+                &mut single_use_usages,
+                &mut macros,
+            );
+        }
+
+        for usage in single_use_usages {
+            if !imports_reused_with_self.contains(&usage.name) {
+                self.found.entry(usage.item_id).or_default().push(usage);
             }
+        }
+    }
 
-            if segments.is_empty() {
-                // keep track of `use {some_module, some_other_module};` usages
-                if let UseTreeKind::Nested(trees) = &use_tree.kind {
-                    for tree in trees {
-                        let segments = &tree.0.prefix.segments;
-                        if segments.len() == 1 {
-                            if let UseTreeKind::Simple(None, _, _) = tree.0.kind {
-                                let name = segments[0].ident.name;
-                                if !macros.contains(&name) {
-                                    single_use_usages.push((name, tree.0.span, false));
-                                }
-                            }
+    fn track_uses(
+        &mut self,
+        cx: &EarlyContext<'_>,
+        item: &Item,
+        imports_reused_with_self: &mut Vec<Symbol>,
+        single_use_usages: &mut Vec<SingleUse>,
+        macros: &mut Vec<Symbol>,
+    ) {
+        if item.span.from_expansion() || item.vis.kind.is_pub() {
+            return;
+        }
+
+        match &item.kind {
+            ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) => {
+                self.check_mod(cx, items);
+            },
+            ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => {
+                macros.push(item.ident.name);
+            },
+            ItemKind::Use(use_tree) => {
+                let segments = &use_tree.prefix.segments;
+
+                // keep track of `use some_module;` usages
+                if segments.len() == 1 {
+                    if let UseTreeKind::Simple(None, _, _) = use_tree.kind {
+                        let name = segments[0].ident.name;
+                        if !macros.contains(&name) {
+                            single_use_usages.push(SingleUse {
+                                name,
+                                span: item.span,
+                                item_id: item.id,
+                                can_suggest: true,
+                            });
                         }
                     }
+                    return;
                 }
-            } else {
-                // keep track of `use self::some_module` usages
-                if segments[0].ident.name == kw::SelfLower {
-                    // simple case such as `use self::module::SomeStruct`
-                    if segments.len() > 1 {
-                        imports_reused_with_self.push(segments[1].ident.name);
-                        return;
-                    }
 
-                    // nested case such as `use self::{module1::Struct1, module2::Struct2}`
+                if segments.is_empty() {
+                    // keep track of `use {some_module, some_other_module};` usages
                     if let UseTreeKind::Nested(trees) = &use_tree.kind {
                         for tree in trees {
                             let segments = &tree.0.prefix.segments;
-                            if !segments.is_empty() {
-                                imports_reused_with_self.push(segments[0].ident.name);
+                            if segments.len() == 1 {
+                                if let UseTreeKind::Simple(None, _, _) = tree.0.kind {
+                                    let name = segments[0].ident.name;
+                                    if !macros.contains(&name) {
+                                        single_use_usages.push(SingleUse {
+                                            name,
+                                            span: tree.0.span,
+                                            item_id: item.id,
+                                            can_suggest: false,
+                                        });
+                                    }
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    // keep track of `use self::some_module` usages
+                    if segments[0].ident.name == kw::SelfLower {
+                        // simple case such as `use self::module::SomeStruct`
+                        if segments.len() > 1 {
+                            imports_reused_with_self.push(segments[1].ident.name);
+                            return;
+                        }
+
+                        // nested case such as `use self::{module1::Struct1, module2::Struct2}`
+                        if let UseTreeKind::Nested(trees) = &use_tree.kind {
+                            for tree in trees {
+                                let segments = &tree.0.prefix.segments;
+                                if !segments.is_empty() {
+                                    imports_reused_with_self.push(segments[0].ident.name);
+                                }
                             }
                         }
                     }
                 }
-            }
-        },
-        _ => {},
+            },
+            _ => {},
+        }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
index 76039923151..a2109038a05 100644
--- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
@@ -168,7 +168,7 @@ impl SlowVectorInit {
         };
     }
 
-    fn emit_lint<'tcx>(cx: &LateContext<'tcx>, slow_fill: &Expr<'_>, vec_alloc: &VecAllocation<'_>, msg: &str) {
+    fn emit_lint(cx: &LateContext<'_>, slow_fill: &Expr<'_>, vec_alloc: &VecAllocation<'_>, msg: &str) {
         let len_expr = Sugg::hir(cx, vec_alloc.len_expr, "len");
 
         span_lint_and_then(cx, SLOW_VECTOR_INITIALIZATION, slow_fill.span, msg, |diag| {
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
index 78e83880e1a..e111c7d2291 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
@@ -582,7 +582,7 @@ fn ident_difference_expr_with_base_location(
         | (Block(_, _), Block(_, _))
         | (Closure(_), Closure(_))
         | (Match(_, _), Match(_, _))
-        | (Loop(_, _), Loop(_, _))
+        | (Loop(_, _, _), Loop(_, _, _))
         | (ForLoop(_, _, _, _), ForLoop(_, _, _, _))
         | (While(_, _, _), While(_, _, _))
         | (If(_, _, _), If(_, _, _))
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs
new file mode 100644
index 00000000000..301aa5798bf
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs
@@ -0,0 +1,53 @@
+use clippy_utils::{numeric_literal::NumericLiteral, source::snippet_with_context};
+use rustc_errors::Applicability;
+use rustc_hir::{BinOpKind, Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Warns for a Bitwise XOR (`^`) operator being probably confused as a powering. It will not trigger if any of the numbers are not in decimal.
+    /// ### Why is this bad?
+    ///	It's most probably a typo and may lead to unexpected behaviours.
+    /// ### Example
+    /// ```rust
+    /// let x = 3_i32 ^ 4_i32;
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let x = 3_i32.pow(4);
+    /// ```
+    #[clippy::version = "1.66.0"]
+    pub SUSPICIOUS_XOR_USED_AS_POW,
+    restriction,
+    "XOR (`^`) operator possibly used as exponentiation operator"
+}
+declare_lint_pass!(ConfusingXorAndPow => [SUSPICIOUS_XOR_USED_AS_POW]);
+
+impl LateLintPass<'_> for ConfusingXorAndPow {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        if !in_external_macro(cx.sess(), expr.span) &&
+        	let ExprKind::Binary(op, left, right) = &expr.kind &&
+            op.node == BinOpKind::BitXor &&
+            left.span.ctxt() == right.span.ctxt() &&
+            let ExprKind::Lit(lit_left) = &left.kind &&
+            let ExprKind::Lit(lit_right) = &right.kind &&
+            let snip_left = snippet_with_context(cx, lit_left.span, lit_left.span.ctxt(), "..", &mut Applicability::MaybeIncorrect) &&
+            let snip_right = snippet_with_context(cx, lit_right.span, lit_right.span.ctxt(), "..", &mut Applicability::MaybeIncorrect) &&
+            let Some(left_val) = NumericLiteral::from_lit_kind(&snip_left.0, &lit_left.node) &&
+            let Some(right_val) = NumericLiteral::from_lit_kind(&snip_right.0, &lit_right.node) &&
+			left_val.is_decimal() &&
+			right_val.is_decimal() {
+					clippy_utils::diagnostics::span_lint_and_sugg(
+					        cx,
+					        SUSPICIOUS_XOR_USED_AS_POW,
+					        expr.span,
+					        "`^` is not the exponentiation operator",
+					        "did you mean to write",
+					        format!("{}.pow({})", left_val.format(), right_val.format()),
+					        Applicability::MaybeIncorrect,
+					    );
+		}
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs
index f46c21e1265..c374529d1ea 100644
--- a/src/tools/clippy/clippy_lints/src/swap.rs
+++ b/src/tools/clippy/clippy_lints/src/swap.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{can_mut_borrow_both, eq_expr_value, std_or_core};
+use clippy_utils::{can_mut_borrow_both, eq_expr_value, in_constant, std_or_core};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
@@ -16,6 +16,8 @@ declare_clippy_lint! {
     /// ### What it does
     /// Checks for manual swapping.
     ///
+    /// Note that the lint will not be emitted in const blocks, as the suggestion would not be applicable.
+    ///
     /// ### Why is this bad?
     /// The `std::mem::swap` function exposes the intent better
     /// without deinitializing or copying either variable.
@@ -138,6 +140,10 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa
 
 /// Implementation of the `MANUAL_SWAP` lint.
 fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) {
+    if in_constant(cx, block.hir_id) {
+        return;
+    }
+
     for w in block.stmts.windows(3) {
         if_chain! {
             // let t = foo();
diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
index 8cf3efc8dc7..63b326048a4 100644
--- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
+++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
@@ -1,9 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_help;
-use rustc_hir::{HirId, Item, ItemKind};
+use clippy_utils::has_repr_attr;
+use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::Const;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -72,7 +72,3 @@ fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'_>, item: &Item<'_
         }
     }
 }
-
-fn has_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
-    cx.tcx.hir().attrs(hir_id).iter().any(|attr| attr.has_name(sym::repr))
-}
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
index 3d4bbbf648c..34642f4b122 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -27,32 +27,24 @@ pub(super) fn check<'tcx>(
 
             // `Repr(C)` <-> unordered type.
             // If the first field of the `Repr(C)` type matches then the transmute is ok
-            (
-                ReducedTy::OrderedFields(_, Some(from_sub_ty)),
-                ReducedTy::UnorderedFields(to_sub_ty),
-            )
-            | (
-                ReducedTy::UnorderedFields(from_sub_ty),
-                ReducedTy::OrderedFields(_, Some(to_sub_ty)),
-            ) => {
+            (ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::UnorderedFields(to_sub_ty))
+            | (ReducedTy::UnorderedFields(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty))) => {
                 from_ty = from_sub_ty;
                 to_ty = to_sub_ty;
                 continue;
-            }
-            (ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::Other(to_sub_ty))
-                if reduced_tys.to_fat_ptr =>
-            {
+            },
+            (ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::Other(to_sub_ty)) if reduced_tys.to_fat_ptr => {
                 from_ty = from_sub_ty;
                 to_ty = to_sub_ty;
                 continue;
-            }
+            },
             (ReducedTy::Other(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty)))
                 if reduced_tys.from_fat_ptr =>
             {
                 from_ty = from_sub_ty;
                 to_ty = to_sub_ty;
                 continue;
-            }
+            },
 
             // ptr <-> ptr
             (ReducedTy::Other(from_sub_ty), ReducedTy::Other(to_sub_ty))
@@ -62,19 +54,19 @@ pub(super) fn check<'tcx>(
                 from_ty = from_sub_ty;
                 to_ty = to_sub_ty;
                 continue;
-            }
+            },
 
             // fat ptr <-> (*size, *size)
             (ReducedTy::Other(_), ReducedTy::UnorderedFields(to_ty))
                 if reduced_tys.from_fat_ptr && is_size_pair(to_ty) =>
             {
                 return false;
-            }
+            },
             (ReducedTy::UnorderedFields(from_ty), ReducedTy::Other(_))
                 if reduced_tys.to_fat_ptr && is_size_pair(from_ty) =>
             {
                 return false;
-            }
+            },
 
             // fat ptr -> some struct | some struct -> fat ptr
             (ReducedTy::Other(_), _) if reduced_tys.from_fat_ptr => {
@@ -85,14 +77,12 @@ pub(super) fn check<'tcx>(
                     &format!("transmute from `{from_ty_orig}` which has an undefined layout"),
                     |diag| {
                         if from_ty_orig.peel_refs() != from_ty.peel_refs() {
-                            diag.note(&format!(
-                                "the contained type `{from_ty}` has an undefined layout"
-                            ));
+                            diag.note(&format!("the contained type `{from_ty}` has an undefined layout"));
                         }
                     },
                 );
                 return true;
-            }
+            },
             (_, ReducedTy::Other(_)) if reduced_tys.to_fat_ptr => {
                 span_lint_and_then(
                     cx,
@@ -101,18 +91,14 @@ pub(super) fn check<'tcx>(
                     &format!("transmute to `{to_ty_orig}` which has an undefined layout"),
                     |diag| {
                         if to_ty_orig.peel_refs() != to_ty.peel_refs() {
-                            diag.note(&format!(
-                                "the contained type `{to_ty}` has an undefined layout"
-                            ));
+                            diag.note(&format!("the contained type `{to_ty}` has an undefined layout"));
                         }
                     },
                 );
                 return true;
-            }
+            },
 
-            (ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(to_ty))
-                if from_ty != to_ty =>
-            {
+            (ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(to_ty)) if from_ty != to_ty => {
                 let same_adt_did = if let (ty::Adt(from_def, from_subs), ty::Adt(to_def, to_subs))
                         = (from_ty.kind(), to_ty.kind())
                         && from_def == to_def
@@ -139,25 +125,19 @@ pub(super) fn check<'tcx>(
                             ));
                         } else {
                             if from_ty_orig.peel_refs() != from_ty {
-                                diag.note(&format!(
-                                    "the contained type `{from_ty}` has an undefined layout"
-                                ));
+                                diag.note(&format!("the contained type `{from_ty}` has an undefined layout"));
                             }
                             if to_ty_orig.peel_refs() != to_ty {
-                                diag.note(&format!(
-                                    "the contained type `{to_ty}` has an undefined layout"
-                                ));
+                                diag.note(&format!("the contained type `{to_ty}` has an undefined layout"));
                             }
                         }
                     },
                 );
                 return true;
-            }
+            },
             (
                 ReducedTy::UnorderedFields(from_ty),
-                ReducedTy::Other(_)
-                | ReducedTy::OrderedFields(..)
-                | ReducedTy::TypeErasure { raw_ptr_only: true },
+                ReducedTy::Other(_) | ReducedTy::OrderedFields(..) | ReducedTy::TypeErasure { raw_ptr_only: true },
             ) => {
                 span_lint_and_then(
                     cx,
@@ -166,18 +146,14 @@ pub(super) fn check<'tcx>(
                     &format!("transmute from `{from_ty_orig}` which has an undefined layout"),
                     |diag| {
                         if from_ty_orig.peel_refs() != from_ty {
-                            diag.note(&format!(
-                                "the contained type `{from_ty}` has an undefined layout"
-                            ));
+                            diag.note(&format!("the contained type `{from_ty}` has an undefined layout"));
                         }
                     },
                 );
                 return true;
-            }
+            },
             (
-                ReducedTy::Other(_)
-                | ReducedTy::OrderedFields(..)
-                | ReducedTy::TypeErasure { raw_ptr_only: true },
+                ReducedTy::Other(_) | ReducedTy::OrderedFields(..) | ReducedTy::TypeErasure { raw_ptr_only: true },
                 ReducedTy::UnorderedFields(to_ty),
             ) => {
                 span_lint_and_then(
@@ -187,25 +163,19 @@ pub(super) fn check<'tcx>(
                     &format!("transmute into `{to_ty_orig}` which has an undefined layout"),
                     |diag| {
                         if to_ty_orig.peel_refs() != to_ty {
-                            diag.note(&format!(
-                                "the contained type `{to_ty}` has an undefined layout"
-                            ));
+                            diag.note(&format!("the contained type `{to_ty}` has an undefined layout"));
                         }
                     },
                 );
                 return true;
-            }
+            },
             (
-                ReducedTy::OrderedFields(..)
-                | ReducedTy::Other(_)
-                | ReducedTy::TypeErasure { raw_ptr_only: true },
-                ReducedTy::OrderedFields(..)
-                | ReducedTy::Other(_)
-                | ReducedTy::TypeErasure { raw_ptr_only: true },
+                ReducedTy::OrderedFields(..) | ReducedTy::Other(_) | ReducedTy::TypeErasure { raw_ptr_only: true },
+                ReducedTy::OrderedFields(..) | ReducedTy::Other(_) | ReducedTy::TypeErasure { raw_ptr_only: true },
             )
             | (ReducedTy::UnorderedFields(_), ReducedTy::UnorderedFields(_)) => {
                 break;
-            }
+            },
         }
     }
 
@@ -223,38 +193,42 @@ struct ReducedTys<'tcx> {
 }
 
 /// Remove references so long as both types are references.
-fn reduce_refs<'tcx>(
-    cx: &LateContext<'tcx>,
-    mut from_ty: Ty<'tcx>,
-    mut to_ty: Ty<'tcx>,
-) -> ReducedTys<'tcx> {
+fn reduce_refs<'tcx>(cx: &LateContext<'tcx>, mut from_ty: Ty<'tcx>, mut to_ty: Ty<'tcx>) -> ReducedTys<'tcx> {
     let mut from_raw_ptr = false;
     let mut to_raw_ptr = false;
-    let (from_fat_ptr, to_fat_ptr) =
-        loop {
-            break match (from_ty.kind(), to_ty.kind()) {
-                (
-                    &(ty::Ref(_, from_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: from_sub_ty, .. })),
-                    &(ty::Ref(_, to_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: to_sub_ty, .. })),
-                ) => {
-                    from_raw_ptr = matches!(*from_ty.kind(), ty::RawPtr(_));
-                    from_ty = from_sub_ty;
-                    to_raw_ptr = matches!(*to_ty.kind(), ty::RawPtr(_));
-                    to_ty = to_sub_ty;
-                    continue;
-                }
-                (
-                    &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })),
-                    _,
-                ) if !unsized_ty.is_sized(cx.tcx, cx.param_env) => (true, false),
-                (
-                    _,
-                    &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })),
-                ) if !unsized_ty.is_sized(cx.tcx, cx.param_env) => (false, true),
-                _ => (false, false),
-            };
+    let (from_fat_ptr, to_fat_ptr) = loop {
+        break match (from_ty.kind(), to_ty.kind()) {
+            (
+                &(ty::Ref(_, from_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: from_sub_ty, .. })),
+                &(ty::Ref(_, to_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: to_sub_ty, .. })),
+            ) => {
+                from_raw_ptr = matches!(*from_ty.kind(), ty::RawPtr(_));
+                from_ty = from_sub_ty;
+                to_raw_ptr = matches!(*to_ty.kind(), ty::RawPtr(_));
+                to_ty = to_sub_ty;
+                continue;
+            },
+            (&(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })), _)
+                if !unsized_ty.is_sized(cx.tcx, cx.param_env) =>
+            {
+                (true, false)
+            },
+            (_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })))
+                if !unsized_ty.is_sized(cx.tcx, cx.param_env) =>
+            {
+                (false, true)
+            },
+            _ => (false, false),
         };
-    ReducedTys { from_ty, to_ty, from_raw_ptr, to_raw_ptr, from_fat_ptr, to_fat_ptr }
+    };
+    ReducedTys {
+        from_ty,
+        to_ty,
+        from_raw_ptr,
+        to_raw_ptr,
+        from_fat_ptr,
+        to_fat_ptr,
+    }
 }
 
 enum ReducedTy<'tcx> {
@@ -277,11 +251,11 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
         return match *ty.kind() {
             ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => {
                 ReducedTy::TypeErasure { raw_ptr_only: false }
-            }
+            },
             ty::Array(sub_ty, _) | ty::Slice(sub_ty) => {
                 ty = sub_ty;
                 continue;
-            }
+            },
             ty::Tuple(args) if args.is_empty() => ReducedTy::TypeErasure { raw_ptr_only: false },
             ty::Tuple(args) => {
                 let mut iter = args.iter();
@@ -293,7 +267,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
                     continue;
                 }
                 ReducedTy::UnorderedFields(ty)
-            }
+            },
             ty::Adt(def, substs) if def.is_struct() => {
                 let mut iter = def
                     .non_enum_variant()
@@ -312,12 +286,10 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
                 } else {
                     ReducedTy::UnorderedFields(ty)
                 }
-            }
-            ty::Adt(def, _)
-                if def.is_enum() && (def.variants().is_empty() || is_c_void(cx, ty)) =>
-            {
+            },
+            ty::Adt(def, _) if def.is_enum() && (def.variants().is_empty() || is_c_void(cx, ty)) => {
                 ReducedTy::TypeErasure { raw_ptr_only: false }
-            }
+            },
             // TODO: Check if the conversion to or from at least one of a union's fields is valid.
             ty::Adt(def, _) if def.is_union() => ReducedTy::TypeErasure { raw_ptr_only: false },
             ty::Foreign(_) | ty::Param(_) => ReducedTy::TypeErasure { raw_ptr_only: false },
@@ -356,11 +328,7 @@ fn same_except_params<'tcx>(subs1: SubstsRef<'tcx>, subs2: SubstsRef<'tcx>) -> b
     for (ty1, ty2) in subs1.types().zip(subs2.types()).filter(|(ty1, ty2)| ty1 != ty2) {
         match (ty1.kind(), ty2.kind()) {
             (ty::Param(_), _) | (_, ty::Param(_)) => (),
-            (ty::Adt(adt1, subs1), ty::Adt(adt2, subs2))
-                if adt1 == adt2 && same_except_params(subs1, subs2) =>
-            {
-                ()
-            }
+            (ty::Adt(adt1, subs1), ty::Adt(adt2, subs2)) if adt1 == adt2 && same_except_params(subs1, subs2) => (),
             _ => return false,
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
index 641cdf5d330..49d863ec03f 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
@@ -1,9 +1,9 @@
+use rustc_hir as hir;
 use rustc_hir::Expr;
 use rustc_hir_typeck::{cast, FnCtxt, Inherited};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{cast::CastKind, Ty};
 use rustc_span::DUMMY_SP;
-use rustc_hir as hir;
 
 // check if the component types of the transmuted collection and the result have different ABI,
 // size or alignment
@@ -55,9 +55,14 @@ fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>
         );
 
         if let Ok(check) = cast::CastCheck::new(
-            &fn_ctxt, e, from_ty, to_ty,
+            &fn_ctxt,
+            e,
+            from_ty,
+            to_ty,
             // We won't show any error to the user, so we don't care what the span is here.
-            DUMMY_SP, DUMMY_SP, hir::Constness::NotConst,
+            DUMMY_SP,
+            DUMMY_SP,
+            hir::Constness::NotConst,
         ) {
             let res = check.do_check(&fn_ctxt);
 
diff --git a/src/tools/clippy/clippy_lints/src/types/box_collection.rs b/src/tools/clippy/clippy_lints/src/types/box_collection.rs
index 802415e163d..43665a922d4 100644
--- a/src/tools/clippy/clippy_lints/src/types/box_collection.rs
+++ b/src/tools/clippy/clippy_lints/src/types/box_collection.rs
@@ -39,12 +39,19 @@ fn get_std_collection(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<Symbol>
     let id = path_def_id(cx, param)?;
     cx.tcx
         .get_diagnostic_name(id)
-        .filter(|&name| matches!(name, sym::HashMap | sym::Vec | sym::HashSet
-            | sym::VecDeque
-            | sym::LinkedList
-            | sym::BTreeMap
-            | sym::BTreeSet
-            | sym::BinaryHeap))
+        .filter(|&name| {
+            matches!(
+                name,
+                sym::HashMap
+                    | sym::Vec
+                    | sym::HashSet
+                    | sym::VecDeque
+                    | sym::LinkedList
+                    | sym::BTreeMap
+                    | sym::BTreeSet
+                    | sym::BinaryHeap
+            )
+        })
         .or_else(|| {
             cx.tcx
                 .lang_items()
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index f6de87b0526..20978e81dc5 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -379,7 +379,9 @@ impl<'tcx> LateLintPass<'tcx> for Types {
     }
 
     fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
-        let is_exported = cx.effective_visibilities.is_exported(cx.tcx.hir().local_def_id(field.hir_id));
+        let is_exported = cx
+            .effective_visibilities
+            .is_exported(cx.tcx.hir().local_def_id(field.hir_id));
 
         self.check_ty(
             cx,
diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
index 2b964b64a33..fae5385ffc8 100644
--- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
+++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
@@ -5,16 +5,12 @@ use rustc_errors::Applicability;
 use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind};
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::LateContext;
+use rustc_middle::ty::TypeVisitable;
 use rustc_span::symbol::sym;
 
 use super::{utils, REDUNDANT_ALLOCATION};
 
-pub(super) fn check(
-    cx: &LateContext<'_>,
-    hir_ty: &hir::Ty<'_>,
-    qpath: &QPath<'_>,
-    def_id: DefId,
-) -> bool {
+pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
     let mut applicability = Applicability::MaybeIncorrect;
     let outer_sym = if Some(def_id) == cx.tcx.lang_items().owned_box() {
         "Box"
@@ -34,12 +30,7 @@ pub(super) fn check(
             hir_ty.span,
             &format!("usage of `{outer_sym}<{generic_snippet}>`"),
             |diag| {
-                diag.span_suggestion(
-                    hir_ty.span,
-                    "try",
-                    format!("{generic_snippet}"),
-                    applicability,
-                );
+                diag.span_suggestion(hir_ty.span, "try", format!("{generic_snippet}"), applicability);
                 diag.note(&format!(
                     "`{generic_snippet}` is already a pointer, `{outer_sym}<{generic_snippet}>` allocates a pointer on the heap"
                 ));
@@ -61,15 +52,16 @@ pub(super) fn check(
         return false
     };
     let inner_span = match qpath_generic_tys(inner_qpath).next() {
-        Some(ty) => {
+        Some(hir_ty) => {
             // Reallocation of a fat pointer causes it to become thin. `hir_ty_to_ty` is safe to use
             // here because `mod.rs` guarantees this lint is only run on types outside of bodies and
             // is not run on locals.
-            if !hir_ty_to_ty(cx.tcx, ty).is_sized(cx.tcx, cx.param_env) {
+            let ty = hir_ty_to_ty(cx.tcx, hir_ty);
+            if ty.has_escaping_bound_vars() || !ty.is_sized(cx.tcx, cx.param_env) {
                 return false;
             }
-            ty.span
-        }
+            hir_ty.span
+        },
         None => return false,
     };
     if inner_sym == outer_sym {
diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
index 9ad2cb853d3..7a3c7cd8a99 100644
--- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
@@ -42,7 +42,7 @@ pub(super) fn check(
             if !ty_ty.has_escaping_bound_vars();
             if ty_ty.is_sized(cx.tcx, cx.param_env);
             if let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes());
-            if ty_ty_size <= box_size_threshold;
+            if ty_ty_size < box_size_threshold;
             then {
                 span_lint_and_sugg(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index d2e675a783e..e8f15a44473 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -68,7 +68,8 @@ impl LateLintPass<'_> for UndocumentedUnsafeBlocks {
             && !in_external_macro(cx.tcx.sess, block.span)
             && !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, block.hir_id)
             && !is_unsafe_from_proc_macro(cx, block.span)
-            && !block_has_safety_comment(cx, block)
+            && !block_has_safety_comment(cx, block.span)
+            && !block_parents_have_safety_comment(cx, block.hir_id)
         {
             let source_map = cx.tcx.sess.source_map();
             let span = if source_map.is_multiline(block.span) {
@@ -126,8 +127,41 @@ fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, span: Span) -> bool {
         .map_or(true, |src| !src.starts_with("unsafe"))
 }
 
+// Checks if any parent {expression, statement, block, local, const, static}
+// has a safety comment
+fn block_parents_have_safety_comment(cx: &LateContext<'_>, id: hir::HirId) -> bool {
+    if let Some(node) = get_parent_node(cx.tcx, id) {
+        return match node {
+            Node::Expr(expr) => !is_branchy(expr) && span_in_body_has_safety_comment(cx, expr.span),
+            Node::Stmt(hir::Stmt {
+                kind:
+                    hir::StmtKind::Local(hir::Local { span, .. })
+                    | hir::StmtKind::Expr(hir::Expr { span, .. })
+                    | hir::StmtKind::Semi(hir::Expr { span, .. }),
+                ..
+            })
+            | Node::Local(hir::Local { span, .. })
+            | Node::Item(hir::Item {
+                kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
+                span,
+                ..
+            }) => span_in_body_has_safety_comment(cx, *span),
+            _ => false,
+        };
+    }
+    false
+}
+
+/// Checks if an expression is "branchy", e.g. loop, match/if/etc.
+fn is_branchy(expr: &hir::Expr<'_>) -> bool {
+    matches!(
+        expr.kind,
+        hir::ExprKind::If(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Match(..)
+    )
+}
+
 /// Checks if the lines immediately preceding the block contain a safety comment.
-fn block_has_safety_comment(cx: &LateContext<'_>, block: &hir::Block<'_>) -> bool {
+fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
     // This intentionally ignores text before the start of a function so something like:
     // ```
     //     // SAFETY: reason
@@ -136,7 +170,7 @@ fn block_has_safety_comment(cx: &LateContext<'_>, block: &hir::Block<'_>) -> boo
     // won't work. This is to avoid dealing with where such a comment should be place relative to
     // attributes and doc comments.
 
-    span_from_macro_expansion_has_safety_comment(cx, block.span) || span_in_body_has_safety_comment(cx, block.span)
+    span_from_macro_expansion_has_safety_comment(cx, span) || span_in_body_has_safety_comment(cx, span)
 }
 
 /// Checks if the lines immediately preceding the item contain a safety comment.
diff --git a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
index 32cd4681201..95258652768 100644
--- a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
+++ b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
@@ -50,7 +50,7 @@ fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext<'_>, span: Span) {
         },
         UseTreeKind::Simple(None, ..) | UseTreeKind::Glob => {},
         UseTreeKind::Nested(ref nested_use_tree) => {
-            for &(ref use_tree, _) in nested_use_tree {
+            for (use_tree, _) in nested_use_tree {
                 check_use_tree(use_tree, cx, span);
             }
         },
diff --git a/src/tools/clippy/clippy_lints/src/unused_peekable.rs b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
index b452be08409..4ee16d9a5e4 100644
--- a/src/tools/clippy/clippy_lints/src/unused_peekable.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
@@ -36,7 +36,7 @@ declare_clippy_lint! {
     ///     // ...
     /// }
     /// ```
-    #[clippy::version = "1.64.0"]
+    #[clippy::version = "1.65.0"]
     pub UNUSED_PEEKABLE,
     nursery,
     "creating a peekable iterator without using any of its methods"
diff --git a/src/tools/clippy/clippy_lints/src/unused_rounding.rs b/src/tools/clippy/clippy_lints/src/unused_rounding.rs
index 5ab351bc29c..aac6719a8dc 100644
--- a/src/tools/clippy/clippy_lints/src/unused_rounding.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_rounding.rs
@@ -30,16 +30,15 @@ declare_clippy_lint! {
 declare_lint_pass!(UnusedRounding => [UNUSED_ROUNDING]);
 
 fn is_useless_rounding(expr: &Expr) -> Option<(&str, String)> {
-    if let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &expr.kind
-        && let method_name = seg.ident.name.as_str()
+    if let ExprKind::MethodCall(box MethodCall { seg:name_ident, receiver, .. }) = &expr.kind
+        && let method_name = name_ident.ident.name.as_str()
         && (method_name == "ceil" || method_name == "round" || method_name == "floor")
         && let ExprKind::Lit(token_lit) = &receiver.kind
         && token_lit.is_semantic_float() {
-            let f = token_lit.symbol.as_str().parse::<f64>().unwrap();
             let mut f_str = token_lit.symbol.to_string();
-            match token_lit.suffix {
-                Some(suffix) => f_str.push_str(suffix.as_str()),
-                None => {}
+            let f = f_str.trim_end_matches('_').parse::<f64>().unwrap();
+            if let Some(suffix) = token_lit.suffix {
+                f_str.push_str(suffix.as_str());
             }
             if f.fract() == 0.0 {
                 Some((method_name, f_str))
diff --git a/src/tools/clippy/clippy_lints/src/unused_unit.rs b/src/tools/clippy/clippy_lints/src/unused_unit.rs
index cd1d90e860b..cad8da18c2f 100644
--- a/src/tools/clippy/clippy_lints/src/unused_unit.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_unit.rs
@@ -1,8 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{position_before_rarrow, snippet_opt};
 use if_chain::if_chain;
-use rustc_ast::ast;
-use rustc_ast::visit::FnKind;
+use rustc_ast::{ast, visit::FnKind, ClosureBinder};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -43,6 +42,11 @@ impl EarlyLintPass for UnusedUnit {
             if let ast::TyKind::Tup(ref vals) = ty.kind;
             if vals.is_empty() && !ty.span.from_expansion() && get_def(span) == get_def(ty.span);
             then {
+                // implicit types in closure signatures are forbidden when `for<...>` is present
+                if let FnKind::Closure(&ClosureBinder::For { .. }, ..) = kind {
+                    return;
+                }
+
                 lint_unneeded_unit_return(cx, ty, span);
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index c6cdf3f85fc..e2860db71a5 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -30,7 +30,6 @@ declare_clippy_lint! {
     ///
     /// ### Known problems
     /// - Unaddressed false negative in fn bodies of trait implementations
-    /// - False positive with associated types in traits (#4140)
     ///
     /// ### Example
     /// ```rust
@@ -103,6 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
             if parameters.as_ref().map_or(true, |params| {
                 !params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
             });
+            if !item.span.from_expansion();
             if !is_from_proc_macro(cx, item); // expensive, should be last check
             then {
                 StackItem::Check {
@@ -234,24 +234,13 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
             then {} else { return; }
         }
         match expr.kind {
-            ExprKind::Struct(QPath::Resolved(_, path), ..) => match path.res {
-                Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => (),
-                Res::Def(DefKind::Variant, _) => lint_path_to_variant(cx, path),
-                _ => span_lint(cx, path.span),
-            },
-            // tuple struct instantiation (`Foo(arg)` or `Enum::Foo(arg)`)
+            ExprKind::Struct(QPath::Resolved(_, path), ..) => check_path(cx, path),
             ExprKind::Call(fun, _) => {
                 if let ExprKind::Path(QPath::Resolved(_, path)) = fun.kind {
-                    if let Res::Def(DefKind::Ctor(ctor_of, _), ..) = path.res {
-                        match ctor_of {
-                            CtorOf::Variant => lint_path_to_variant(cx, path),
-                            CtorOf::Struct => span_lint(cx, path.span),
-                        }
-                    }
+                    check_path(cx, path);
                 }
             },
-            // unit enum variants (`Enum::A`)
-            ExprKind::Path(QPath::Resolved(_, path)) => lint_path_to_variant(cx, path),
+            ExprKind::Path(QPath::Resolved(_, path)) => check_path(cx, path),
             _ => (),
         }
     }
@@ -267,15 +256,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
                  | PatKind::Struct(QPath::Resolved(_, path), _, _) = pat.kind;
             if cx.typeck_results().pat_ty(pat) == cx.tcx.type_of(impl_id);
             then {
-                match path.res {
-                    Res::Def(DefKind::Ctor(ctor_of, _), ..) => match ctor_of {
-                            CtorOf::Variant => lint_path_to_variant(cx, path),
-                            CtorOf::Struct => span_lint(cx, path.span),
-                    },
-                    Res::Def(DefKind::Variant, ..) => lint_path_to_variant(cx, path),
-                    Res::Def(DefKind::Struct, ..) => span_lint(cx, path.span),
-                    _ => ()
-                }
+                check_path(cx, path);
             }
         }
     }
@@ -313,6 +294,16 @@ fn span_lint(cx: &LateContext<'_>, span: Span) {
     );
 }
 
+fn check_path(cx: &LateContext<'_>, path: &Path<'_>) {
+    match path.res {
+        Res::Def(DefKind::Ctor(CtorOf::Variant, _) | DefKind::Variant, ..) => {
+            lint_path_to_variant(cx, path);
+        },
+        Res::Def(DefKind::Ctor(CtorOf::Struct, _) | DefKind::Struct, ..) => span_lint(cx, path.span),
+        _ => (),
+    }
+}
+
 fn lint_path_to_variant(cx: &LateContext<'_>, path: &Path<'_>) {
     if let [.., self_seg, _variant] = path.segments {
         let span = path
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index 668123e4d6e..b37d4239477 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -53,11 +53,11 @@ impl DisallowedPath {
         path
     }
 
-    pub fn reason(&self) -> Option<&str> {
+    pub fn reason(&self) -> Option<String> {
         match self {
             Self::WithReason {
                 reason: Some(reason), ..
-            } => Some(reason),
+            } => Some(format!("{reason} (from clippy.toml)")),
             _ => None,
         }
     }
@@ -213,7 +213,7 @@ define_Conf! {
     ///
     /// Suppress lints whenever the suggested change would cause breakage for other crates.
     (avoid_breaking_exported_api: bool = true),
-    /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP.
+    /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION.
     ///
     /// The minimum rust version that the project supports
     (msrv: Option<String> = None),
@@ -335,6 +335,12 @@ define_Conf! {
     ///
     /// Enables verbose mode. Triggers if there is more than one uppercase char next to each other
     (upper_case_acronyms_aggressive: bool = false),
+    /// Lint: MANUAL_LET_ELSE.
+    ///
+    /// Whether the matches should be considered by the lint, and whether there should
+    /// be filtering for common types.
+    (matches_for_let_else: crate::manual_let_else::MatchLintBehaviour =
+        crate::manual_let_else::MatchLintBehaviour::WellKnownTypes),
     /// Lint: _CARGO_COMMON_METADATA.
     ///
     /// For internal testing only, ignores the current `publish` settings in the Cargo manifest.
@@ -373,23 +379,36 @@ define_Conf! {
     (max_include_file_size: u64 = 1_000_000),
     /// Lint: EXPECT_USED.
     ///
-    /// Whether `expect` should be allowed in test functions
+    /// Whether `expect` should be allowed within `#[cfg(test)]`
     (allow_expect_in_tests: bool = false),
     /// Lint: UNWRAP_USED.
     ///
-    /// Whether `unwrap` should be allowed in test functions
+    /// Whether `unwrap` should be allowed in test cfg
     (allow_unwrap_in_tests: bool = false),
     /// Lint: DBG_MACRO.
     ///
     /// Whether `dbg!` should be allowed in test functions
     (allow_dbg_in_tests: bool = false),
-    /// Lint: RESULT_LARGE_ERR
+    /// Lint: PRINT_STDOUT, PRINT_STDERR.
+    ///
+    /// Whether print macros (ex. `println!`) should be allowed in test functions
+    (allow_print_in_tests: bool = false),
+    /// Lint: RESULT_LARGE_ERR.
     ///
     /// The maximum size of the `Err`-variant in a `Result` returned from a function
     (large_error_threshold: u64 = 128),
+    /// Lint: MUTABLE_KEY.
+    ///
+    /// A list of paths to types that should be treated like `Arc`, i.e. ignored but
+    /// for the generic parameters for determining interior mutability
+    (ignore_interior_mutability: Vec<String> = Vec::from(["bytes::Bytes".into()])),
 }
 
 /// Search for the configuration file.
+///
+/// # Errors
+///
+/// Returns any unexpected filesystem error encountered when searching for the config file
 pub fn lookup_conf_file() -> io::Result<Option<PathBuf>> {
     /// Possible filename to search for.
     const CONFIG_FILE_NAMES: [&str; 2] = [".clippy.toml", "clippy.toml"];
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
index 096b601572b..4b33d492a0e 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
@@ -2,7 +2,7 @@ use clippy_utils::consts::{constant_simple, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::match_type;
-use clippy_utils::{def_path_res, is_expn_of, match_def_path, paths};
+use clippy_utils::{def_path_def_ids, is_expn_of, match_def_path, paths};
 use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
         }
 
         for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] {
-            if let Some(def_id) = def_path_res(cx, module, None).opt_def_id() {
+            for def_id in def_path_def_ids(cx, module) {
                 for item in cx.tcx.module_children(def_id).iter() {
                     if_chain! {
                         if let Res::Def(DefKind::Const, item_def_id) = item.res;
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
index 22a5aa5351a..680935f2329 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
@@ -3,7 +3,7 @@ use clippy_utils::def_path_res;
 use clippy_utils::diagnostics::span_lint;
 use if_chain::if_chain;
 use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def::DefKind;
 use rustc_hir::Item;
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass};
@@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths {
 // This is not a complete resolver for paths. It works on all the paths currently used in the paths
 // module.  That's all it does and all it needs to do.
 pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
-    if def_path_res(cx, path, None) != Res::Err {
+    if !def_path_res(cx, path).is_empty() {
         return true;
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
index 0dac64376b0..1aebb8b3104 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
@@ -256,7 +256,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
     }
 }
 
-pub(super) fn is_lint_ref_type<'tcx>(cx: &LateContext<'tcx>, ty: &hir::Ty<'_>) -> bool {
+pub(super) fn is_lint_ref_type(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
     if let TyKind::Rptr(
         _,
         MutTy {
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
index cfba7fa8791..393988dbad3 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{def_path_res, is_lint_allowed, match_any_def_paths, peel_hir_expr_refs};
+use clippy_utils::{def_path_def_ids, is_lint_allowed, match_any_def_paths, peel_hir_expr_refs};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_data_structures::fx::FxHashSet;
@@ -11,9 +11,9 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, ExprKind, Local, Mutability, Node};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::interpret::{Allocation, ConstValue, GlobalAlloc};
-use rustc_middle::ty::{self, AssocKind, DefIdTree, Ty};
+use rustc_middle::ty::{self, DefIdTree, Ty};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 
 use std::str;
@@ -110,7 +110,7 @@ impl UnnecessaryDefPath {
             // Extract the path to the matched type
             if let Some(segments) = path_to_matched_type(cx, item_arg);
             let segments: Vec<&str> = segments.iter().map(|sym| &**sym).collect();
-            if let Some(def_id) = inherent_def_path_res(cx, &segments[..]);
+            if let Some(def_id) = def_path_def_ids(cx, &segments[..]).next();
             then {
                 // Check if the target item is a diagnostic item or LangItem.
                 #[rustfmt::skip]
@@ -133,11 +133,11 @@ impl UnnecessaryDefPath {
                 let has_ctor = match cx.tcx.def_kind(def_id) {
                     DefKind::Struct => {
                         let variant = cx.tcx.adt_def(def_id).non_enum_variant();
-                        variant.ctor_def_id.is_some() && variant.fields.iter().all(|f| f.vis.is_public())
+                        variant.ctor.is_some() && variant.fields.iter().all(|f| f.vis.is_public())
                     },
                     DefKind::Variant => {
                         let variant = cx.tcx.adt_def(cx.tcx.parent(def_id)).variant_with_id(def_id);
-                        variant.ctor_def_id.is_some() && variant.fields.iter().all(|f| f.vis.is_public())
+                        variant.ctor.is_some() && variant.fields.iter().all(|f| f.vis.is_public())
                     },
                     _ => false,
                 };
@@ -209,7 +209,7 @@ impl UnnecessaryDefPath {
     fn check_array(&mut self, cx: &LateContext<'_>, elements: &[Expr<'_>], span: Span) {
         let Some(path) = path_from_array(elements) else { return };
 
-        if let Some(def_id) = inherent_def_path_res(cx, &path.iter().map(AsRef::as_ref).collect::<Vec<_>>()) {
+        for def_id in def_path_def_ids(cx, &path.iter().map(AsRef::as_ref).collect::<Vec<_>>()) {
             self.array_def_ids.insert((def_id, span));
         }
     }
@@ -246,7 +246,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Ve
 
 fn read_mir_alloc_def_path<'tcx>(cx: &LateContext<'tcx>, alloc: &'tcx Allocation, ty: Ty<'_>) -> Option<Vec<String>> {
     let (alloc, ty) = if let ty::Ref(_, ty, Mutability::Not) = *ty.kind() {
-        let &alloc = alloc.provenance().values().next()?;
+        let &alloc = alloc.provenance().ptrs().values().next()?;
         if let GlobalAlloc::Memory(alloc) = cx.tcx.global_alloc(alloc) {
             (alloc.inner(), ty)
         } else {
@@ -262,6 +262,7 @@ fn read_mir_alloc_def_path<'tcx>(cx: &LateContext<'tcx>, alloc: &'tcx Allocation
     {
         alloc
             .provenance()
+            .ptrs()
             .values()
             .map(|&alloc| {
                 if let GlobalAlloc::Memory(alloc) = cx.tcx.global_alloc(alloc) {
@@ -293,38 +294,6 @@ fn path_from_array(exprs: &[Expr<'_>]) -> Option<Vec<String>> {
         .collect()
 }
 
-// def_path_res will match field names before anything else, but for this we want to match
-// inherent functions first.
-fn inherent_def_path_res(cx: &LateContext<'_>, segments: &[&str]) -> Option<DefId> {
-    def_path_res(cx, segments, None).opt_def_id().map(|def_id| {
-        if cx.tcx.def_kind(def_id) == DefKind::Field {
-            let method_name = *segments.last().unwrap();
-            cx.tcx
-                .def_key(def_id)
-                .parent
-                .and_then(|parent_idx| {
-                    cx.tcx
-                        .inherent_impls(DefId {
-                            index: parent_idx,
-                            krate: def_id.krate,
-                        })
-                        .iter()
-                        .find_map(|impl_id| {
-                            cx.tcx.associated_items(*impl_id).find_by_name_and_kind(
-                                cx.tcx,
-                                Ident::from_str(method_name),
-                                AssocKind::Fn,
-                                *impl_id,
-                            )
-                        })
-                })
-                .map_or(def_id, |item| item.def_id)
-        } else {
-            def_id
-        }
-    })
-}
-
 fn get_lang_item_name(cx: &LateContext<'_>, def_id: DefId) -> Option<&'static str> {
     if let Some((lang_item, _)) = cx.tcx.lang_items().iter().find(|(_, id)| *id == def_id) {
         Some(lang_item.variant_name())
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index 36574198f91..6b321765bc0 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -1,6 +1,7 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::macros::{root_macro_call_first_node, FormatArgsExpn, MacroCall};
 use clippy_utils::source::{expand_past_previous_comma, snippet_opt};
+use clippy_utils::{is_in_cfg_test, is_in_test_function};
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, HirIdMap, Impl, Item, ItemKind};
@@ -232,6 +233,16 @@ declare_clippy_lint! {
 #[derive(Default)]
 pub struct Write {
     in_debug_impl: bool,
+    allow_print_in_tests: bool,
+}
+
+impl Write {
+    pub fn new(allow_print_in_tests: bool) -> Self {
+        Self {
+            allow_print_in_tests,
+            ..Default::default()
+        }
+    }
 }
 
 impl_lint_pass!(Write => [
@@ -271,13 +282,15 @@ impl<'tcx> LateLintPass<'tcx> for Write {
             .as_ref()
             .map_or(false, |crate_name| crate_name == "build_script_build");
 
+        let allowed_in_tests = self.allow_print_in_tests
+            && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id));
         match diag_name {
-            sym::print_macro | sym::println_macro => {
+            sym::print_macro | sym::println_macro if !allowed_in_tests => {
                 if !is_build_script {
                     span_lint(cx, PRINT_STDOUT, macro_call.span, &format!("use of `{name}!`"));
                 }
             },
-            sym::eprint_macro | sym::eprintln_macro => {
+            sym::eprint_macro | sym::eprintln_macro if !allowed_in_tests => {
                 span_lint(cx, PRINT_STDERR, macro_call.span, &format!("use of `{name}!`"));
             },
             sym::write_macro | sym::writeln_macro => {},
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index 83fee7bb39c..fb9f4740ecc 100644
--- a/src/tools/clippy/clippy_utils/Cargo.toml
+++ b/src/tools/clippy/clippy_utils/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_utils"
-version = "0.1.66"
+version = "0.1.67"
 edition = "2021"
 publish = false
 
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 87b378bfd19..6bcf0bbd7eb 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -148,11 +148,19 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
         (Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value),
         (Call(lc, la), Call(rc, ra)) => eq_expr(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
         (
-            MethodCall(box ast::MethodCall { seg: ls, receiver: lr, args: la, .. }),
-            MethodCall(box ast::MethodCall { seg: rs, receiver: rr, args: ra, .. })
-        ) => {
-            eq_path_seg(ls, rs) && eq_expr(lr, rr) && over(la, ra, |l, r| eq_expr(l, r))
-        },
+            MethodCall(box ast::MethodCall {
+                seg: ls,
+                receiver: lr,
+                args: la,
+                ..
+            }),
+            MethodCall(box ast::MethodCall {
+                seg: rs,
+                receiver: rr,
+                args: ra,
+                ..
+            }),
+        ) => eq_path_seg(ls, rs) && eq_expr(lr, rr) && over(la, ra, |l, r| eq_expr(l, r)),
         (Binary(lo, ll, lr), Binary(ro, rl, rr)) => lo.node == ro.node && eq_expr(ll, rl) && eq_expr(lr, rr),
         (Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r),
         (Lit(l), Lit(r)) => l == r,
@@ -163,7 +171,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
         (ForLoop(lp, li, lt, ll), ForLoop(rp, ri, rt, rl)) => {
             eq_label(ll, rl) && eq_pat(lp, rp) && eq_expr(li, ri) && eq_block(lt, rt)
         },
-        (Loop(lt, ll), Loop(rt, rl)) => eq_label(ll, rl) && eq_block(lt, rt),
+        (Loop(lt, ll, _), Loop(rt, rl, _)) => eq_label(ll, rl) && eq_block(lt, rt),
         (Block(lb, ll), Block(rb, rl)) => eq_label(ll, rl) && eq_block(lb, rb),
         (TryBlock(l), TryBlock(r)) => eq_block(l, r),
         (Yield(l), Yield(r)) | (Ret(l), Ret(r)) => eq_expr_opt(l, r),
@@ -191,7 +199,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
                 fn_decl: rf,
                 body: re,
                 ..
-            })
+            }),
         ) => {
             eq_closure_binder(lb, rb)
                 && lc == rc
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 07e4ef6a2fe..315aea9aa09 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -51,8 +51,8 @@ pub enum Constant {
 impl PartialEq for Constant {
     fn eq(&self, other: &Self) -> bool {
         match (self, other) {
-            (&Self::Str(ref ls), &Self::Str(ref rs)) => ls == rs,
-            (&Self::Binary(ref l), &Self::Binary(ref r)) => l == r,
+            (Self::Str(ls), Self::Str(rs)) => ls == rs,
+            (Self::Binary(l), Self::Binary(r)) => l == r,
             (&Self::Char(l), &Self::Char(r)) => l == r,
             (&Self::Int(l), &Self::Int(r)) => l == r,
             (&Self::F64(l), &Self::F64(r)) => {
@@ -69,8 +69,8 @@ impl PartialEq for Constant {
             },
             (&Self::Bool(l), &Self::Bool(r)) => l == r,
             (&Self::Vec(ref l), &Self::Vec(ref r)) | (&Self::Tuple(ref l), &Self::Tuple(ref r)) => l == r,
-            (&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => ls == rs && lv == rv,
-            (&Self::Ref(ref lb), &Self::Ref(ref rb)) => *lb == *rb,
+            (Self::Repeat(lv, ls), Self::Repeat(rv, rs)) => ls == rs && lv == rv,
+            (Self::Ref(lb), Self::Ref(rb)) => *lb == *rb,
             // TODO: are there inter-type equalities?
             _ => false,
         }
@@ -126,8 +126,8 @@ impl Hash for Constant {
 impl Constant {
     pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self) -> Option<Ordering> {
         match (left, right) {
-            (&Self::Str(ref ls), &Self::Str(ref rs)) => Some(ls.cmp(rs)),
-            (&Self::Char(ref l), &Self::Char(ref r)) => Some(l.cmp(r)),
+            (Self::Str(ls), Self::Str(rs)) => Some(ls.cmp(rs)),
+            (Self::Char(l), Self::Char(r)) => Some(l.cmp(r)),
             (&Self::Int(l), &Self::Int(r)) => match *cmp_type.kind() {
                 ty::Int(int_ty) => Some(sext(tcx, l, int_ty).cmp(&sext(tcx, r, int_ty))),
                 ty::Uint(_) => Some(l.cmp(&r)),
@@ -135,8 +135,8 @@ impl Constant {
             },
             (&Self::F64(l), &Self::F64(r)) => l.partial_cmp(&r),
             (&Self::F32(l), &Self::F32(r)) => l.partial_cmp(&r),
-            (&Self::Bool(ref l), &Self::Bool(ref r)) => Some(l.cmp(r)),
-            (&Self::Tuple(ref l), &Self::Tuple(ref r)) if l.len() == r.len() => match *cmp_type.kind() {
+            (Self::Bool(l), Self::Bool(r)) => Some(l.cmp(r)),
+            (Self::Tuple(l), Self::Tuple(r)) if l.len() == r.len() => match *cmp_type.kind() {
                 ty::Tuple(tys) if tys.len() == l.len() => l
                     .iter()
                     .zip(r)
@@ -146,17 +146,16 @@ impl Constant {
                     .unwrap_or_else(|| Some(l.len().cmp(&r.len()))),
                 _ => None,
             },
-            (&Self::Vec(ref l), &Self::Vec(ref r)) => {
-                let cmp_type = match *cmp_type.kind() {
-                    ty::Array(ty, _) | ty::Slice(ty) => ty,
-                    _ => return None,
+            (Self::Vec(l), Self::Vec(r)) => {
+                let (ty::Array(cmp_type, _) | ty::Slice(cmp_type)) = *cmp_type.kind() else {
+                    return None
                 };
                 iter::zip(l, r)
                     .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri))
                     .find(|r| r.map_or(true, |o| o != Ordering::Equal))
                     .unwrap_or_else(|| Some(l.len().cmp(&r.len())))
             },
-            (&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => {
+            (Self::Repeat(lv, ls), Self::Repeat(rv, rs)) => {
                 match Self::partial_cmp(
                     tcx,
                     match *cmp_type.kind() {
@@ -170,7 +169,7 @@ impl Constant {
                     x => x,
                 }
             },
-            (&Self::Ref(ref lb), &Self::Ref(ref rb)) => Self::partial_cmp(
+            (Self::Ref(lb), Self::Ref(rb)) => Self::partial_cmp(
                 tcx,
                 match *cmp_type.kind() {
                     ty::Ref(_, ty, _) => ty,
@@ -401,10 +400,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
         use self::Constant::{Int, F32, F64};
         match *o {
             Int(value) => {
-                let ity = match *ty.kind() {
-                    ty::Int(ity) => ity,
-                    _ => return None,
-                };
+                let ty::Int(ity) = *ty.kind() else { return None };
                 // sign extend
                 let value = sext(self.lcx.tcx, value, ity);
                 let value = value.checked_neg()?;
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index 78f93755b72..16b160b6fd2 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -72,8 +72,8 @@ pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<Mult
 ///    |
 ///    = help: consider using `f64::NAN` if you would like a constant representing NaN
 /// ```
-pub fn span_lint_and_help<'a, T: LintContext>(
-    cx: &'a T,
+pub fn span_lint_and_help<T: LintContext>(
+    cx: &T,
     lint: &'static Lint,
     span: impl Into<MultiSpan>,
     msg: &str,
@@ -114,8 +114,8 @@ pub fn span_lint_and_help<'a, T: LintContext>(
 /// 10 |     forget(&SomeStruct);
 ///    |            ^^^^^^^^^^^
 /// ```
-pub fn span_lint_and_note<'a, T: LintContext>(
-    cx: &'a T,
+pub fn span_lint_and_note<T: LintContext>(
+    cx: &T,
     lint: &'static Lint,
     span: impl Into<MultiSpan>,
     msg: &str,
@@ -192,8 +192,8 @@ pub fn span_lint_hir_and_then(
 ///     = note: `-D fold-any` implied by `-D warnings`
 /// ```
 #[cfg_attr(feature = "internal", allow(clippy::collapsible_span_lint_calls))]
-pub fn span_lint_and_sugg<'a, T: LintContext>(
-    cx: &'a T,
+pub fn span_lint_and_sugg<T: LintContext>(
+    cx: &T,
     lint: &'static Lint,
     sp: Span,
     msg: &str,
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index abe10f3c81e..c944fc51e82 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -8,7 +8,7 @@ use rustc_hir::HirIdMap;
 use rustc_hir::{
     ArrayLen, BinOpKind, BindingAnnotation, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg,
     GenericArgs, Guard, HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path,
-    PathSegment, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
+    PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
 };
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::LateContext;
@@ -131,13 +131,10 @@ impl HirEqInterExpr<'_, '_, '_> {
             ([], 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 (left, right) = match (
+                let (Some(left), Some(right)) = (
                     snippet_opt(self.inner.cx, left.span),
                     snippet_opt(self.inner.cx, right.span),
-                ) {
-                    (Some(left), Some(right)) => (left, right),
-                    _ => return true,
-                };
+                ) else { return true };
                 let mut left_pos = 0;
                 let left = tokenize(&left)
                     .map(|t| {
@@ -269,7 +266,7 @@ impl HirEqInterExpr<'_, '_, '_> {
             (&ExprKind::Let(l), &ExprKind::Let(r)) => {
                 self.eq_pat(l.pat, r.pat) && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) && self.eq_expr(l.init, r.init)
             },
-            (&ExprKind::Lit(ref l), &ExprKind::Lit(ref r)) => l.node == r.node,
+            (ExprKind::Lit(l), ExprKind::Lit(r)) => l.node == r.node,
             (&ExprKind::Loop(lb, ref ll, ref lls, _), &ExprKind::Loop(rb, ref rl, ref rls, _)) => {
                 lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.name == r.ident.name)
             },
@@ -294,8 +291,8 @@ impl HirEqInterExpr<'_, '_, '_> {
             (&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => {
                 self.eq_expr(le, re) && self.eq_array_length(ll, rl)
             },
-            (&ExprKind::Ret(ref l), &ExprKind::Ret(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)),
-            (&ExprKind::Path(ref l), &ExprKind::Path(ref r)) => self.eq_qpath(l, r),
+            (ExprKind::Ret(l), ExprKind::Ret(r)) => both(l, r, |l, r| self.eq_expr(l, r)),
+            (ExprKind::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r),
             (&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => {
                 self.eq_qpath(l_path, r_path)
                     && both(lo, ro, |l, r| self.eq_expr(l, r))
@@ -365,7 +362,7 @@ impl HirEqInterExpr<'_, '_, '_> {
                 }
                 eq
             },
-            (&PatKind::Path(ref l), &PatKind::Path(ref r)) => self.eq_qpath(l, r),
+            (PatKind::Path(l), PatKind::Path(r)) => self.eq_qpath(l, r),
             (&PatKind::Lit(l), &PatKind::Lit(r)) => self.eq_expr(l, r),
             (&PatKind::Tuple(l, ls), &PatKind::Tuple(r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)),
             (&PatKind::Range(ref ls, ref le, li), &PatKind::Range(ref rs, ref re, ri)) => {
@@ -432,13 +429,11 @@ impl HirEqInterExpr<'_, '_, '_> {
         match (&left.kind, &right.kind) {
             (&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
             (&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_array_length(ll, rl),
-            (&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => {
-                l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty)
-            },
-            (&TyKind::Rptr(_, ref l_rmut), &TyKind::Rptr(_, ref r_rmut)) => {
+            (TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty),
+            (TyKind::Rptr(_, l_rmut), TyKind::Rptr(_, r_rmut)) => {
                 l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty)
             },
-            (&TyKind::Path(ref l), &TyKind::Path(ref r)) => self.eq_qpath(l, r),
+            (TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r),
             (&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
             (&TyKind::Infer, &TyKind::Infer) => true,
             _ => false,
@@ -1033,6 +1028,14 @@ pub fn hash_stmt(cx: &LateContext<'_>, s: &Stmt<'_>) -> u64 {
     h.finish()
 }
 
+pub fn is_bool(ty: &Ty<'_>) -> bool {
+    if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
+        matches!(path.res, Res::PrimTy(PrimTy::Bool))
+    } else {
+        false
+    }
+}
+
 pub fn hash_expr(cx: &LateContext<'_>, e: &Expr<'_>) -> u64 {
     let mut h = SpanlessHash::new(cx);
     h.hash_expr(e);
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 3f93b9b491d..9e2682925a2 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -66,7 +66,7 @@ pub mod visitors;
 pub use self::attrs::*;
 pub use self::check_proc_macro::{is_from_proc_macro, is_span_if, is_span_match};
 pub use self::hir_utils::{
-    both, count_eq, eq_expr_value, hash_expr, hash_stmt, over, HirEqInterExpr, SpanlessEq, SpanlessHash,
+    both, count_eq, eq_expr_value, hash_expr, hash_stmt, is_bool, over, HirEqInterExpr, SpanlessEq, SpanlessHash,
 };
 
 use core::ops::ControlFlow;
@@ -80,17 +80,16 @@ use rustc_ast::ast::{self, LitKind};
 use rustc_ast::Attribute;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::unhash::UnhashMap;
-use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Namespace, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::hir_id::{HirIdMap, HirIdSet};
 use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
 use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk};
 use rustc_hir::{
-    def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Constness,
-    Destination, Expr, ExprKind, FnDecl, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind,
-    LangItem, Local, MatchSource, Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy,
-    QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp,
+    self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Constness, Destination,
+    Expr, ExprKind, FnDecl, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, IsAsync, Item, ItemKind, LangItem, Local,
+    MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind,
+    TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp,
 };
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::{LateContext, Level, Lint, LintContext};
@@ -109,11 +108,10 @@ use rustc_middle::ty::{FloatTy, IntTy, UintTy};
 use rustc_semver::RustcVersion;
 use rustc_session::Session;
 use rustc_span::hygiene::{ExpnKind, MacroKind};
-use rustc_span::source_map::original_sp;
 use rustc_span::source_map::SourceMap;
 use rustc_span::sym;
-use rustc_span::symbol::{kw, Symbol};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::symbol::{kw, Ident, Symbol};
+use rustc_span::Span;
 use rustc_target::abi::Integer;
 
 use crate::consts::{constant, Constant};
@@ -436,11 +434,7 @@ pub fn is_expr_path_def_path(cx: &LateContext<'_>, expr: &Expr<'_>, segments: &[
 
 /// If `maybe_path` is a path node which resolves to an item, resolves it to a `DefId` and checks if
 /// it matches the given lang item.
-pub fn is_path_lang_item<'tcx>(
-    cx: &LateContext<'_>,
-    maybe_path: &impl MaybePath<'tcx>,
-    lang_item: LangItem,
-) -> bool {
+pub fn is_path_lang_item<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>, lang_item: LangItem) -> bool {
     path_def_id(cx, maybe_path).map_or(false, |id| cx.tcx.lang_items().get(lang_item) == Some(id))
 }
 
@@ -535,125 +529,177 @@ pub fn path_def_id<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>
     path_res(cx, maybe_path).opt_def_id()
 }
 
-fn find_primitive<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<Item = DefId> + 'tcx {
-    let single = |ty| tcx.incoherent_impls(ty).iter().copied();
-    let empty = || [].iter().copied();
-    match name {
-        "bool" => single(BoolSimplifiedType),
-        "char" => single(CharSimplifiedType),
-        "str" => single(StrSimplifiedType),
-        "array" => single(ArraySimplifiedType),
-        "slice" => single(SliceSimplifiedType),
+fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<Item = DefId> + 'tcx {
+    let ty = match name {
+        "bool" => BoolSimplifiedType,
+        "char" => CharSimplifiedType,
+        "str" => StrSimplifiedType,
+        "array" => ArraySimplifiedType,
+        "slice" => SliceSimplifiedType,
         // FIXME: rustdoc documents these two using just `pointer`.
         //
         // Maybe this is something we should do here too.
-        "const_ptr" => single(PtrSimplifiedType(Mutability::Not)),
-        "mut_ptr" => single(PtrSimplifiedType(Mutability::Mut)),
-        "isize" => single(IntSimplifiedType(IntTy::Isize)),
-        "i8" => single(IntSimplifiedType(IntTy::I8)),
-        "i16" => single(IntSimplifiedType(IntTy::I16)),
-        "i32" => single(IntSimplifiedType(IntTy::I32)),
-        "i64" => single(IntSimplifiedType(IntTy::I64)),
-        "i128" => single(IntSimplifiedType(IntTy::I128)),
-        "usize" => single(UintSimplifiedType(UintTy::Usize)),
-        "u8" => single(UintSimplifiedType(UintTy::U8)),
-        "u16" => single(UintSimplifiedType(UintTy::U16)),
-        "u32" => single(UintSimplifiedType(UintTy::U32)),
-        "u64" => single(UintSimplifiedType(UintTy::U64)),
-        "u128" => single(UintSimplifiedType(UintTy::U128)),
-        "f32" => single(FloatSimplifiedType(FloatTy::F32)),
-        "f64" => single(FloatSimplifiedType(FloatTy::F64)),
-        _ => empty(),
-    }
-}
-
-/// Resolves a def path like `std::vec::Vec`. `namespace_hint` can be supplied to disambiguate
-/// between `std::vec` the module and `std::vec` the macro
-///
-/// This function is expensive and should be used sparingly.
-pub fn def_path_res(cx: &LateContext<'_>, path: &[&str], namespace_hint: Option<Namespace>) -> Res {
-    fn item_child_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: &str, matches_ns: impl Fn(Res) -> bool) -> Option<Res> {
-        match tcx.def_kind(def_id) {
-            DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx
-                .module_children(def_id)
-                .iter()
-                .find(|item| item.ident.name.as_str() == name && matches_ns(item.res.expect_non_local()))
-                .map(|child| child.res.expect_non_local()),
-            DefKind::Impl => tcx
-                .associated_item_def_ids(def_id)
-                .iter()
-                .copied()
-                .find(|assoc_def_id| tcx.item_name(*assoc_def_id).as_str() == name)
-                .map(|assoc_def_id| Res::Def(tcx.def_kind(assoc_def_id), assoc_def_id)),
-            DefKind::Struct | DefKind::Union => tcx
-                .adt_def(def_id)
-                .non_enum_variant()
-                .fields
-                .iter()
-                .find(|f| f.name.as_str() == name)
-                .map(|f| Res::Def(DefKind::Field, f.did)),
-            _ => None,
+        "const_ptr" => PtrSimplifiedType(Mutability::Not),
+        "mut_ptr" => PtrSimplifiedType(Mutability::Mut),
+        "isize" => IntSimplifiedType(IntTy::Isize),
+        "i8" => IntSimplifiedType(IntTy::I8),
+        "i16" => IntSimplifiedType(IntTy::I16),
+        "i32" => IntSimplifiedType(IntTy::I32),
+        "i64" => IntSimplifiedType(IntTy::I64),
+        "i128" => IntSimplifiedType(IntTy::I128),
+        "usize" => UintSimplifiedType(UintTy::Usize),
+        "u8" => UintSimplifiedType(UintTy::U8),
+        "u16" => UintSimplifiedType(UintTy::U16),
+        "u32" => UintSimplifiedType(UintTy::U32),
+        "u64" => UintSimplifiedType(UintTy::U64),
+        "u128" => UintSimplifiedType(UintTy::U128),
+        "f32" => FloatSimplifiedType(FloatTy::F32),
+        "f64" => FloatSimplifiedType(FloatTy::F64),
+        _ => return [].iter().copied(),
+    };
+
+    tcx.incoherent_impls(ty).iter().copied()
+}
+
+fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> {
+    match tcx.def_kind(def_id) {
+        DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx
+            .module_children(def_id)
+            .iter()
+            .filter(|item| item.ident.name == name)
+            .map(|child| child.res.expect_non_local())
+            .collect(),
+        DefKind::Impl => tcx
+            .associated_item_def_ids(def_id)
+            .iter()
+            .copied()
+            .filter(|assoc_def_id| tcx.item_name(*assoc_def_id) == name)
+            .map(|assoc_def_id| Res::Def(tcx.def_kind(assoc_def_id), assoc_def_id))
+            .collect(),
+        _ => Vec::new(),
+    }
+}
+
+fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symbol) -> Vec<Res> {
+    let hir = tcx.hir();
+
+    let root_mod;
+    let item_kind = match hir.find_by_def_id(local_id) {
+        Some(Node::Crate(r#mod)) => {
+            root_mod = ItemKind::Mod(r#mod);
+            &root_mod
+        },
+        Some(Node::Item(item)) => &item.kind,
+        _ => return Vec::new(),
+    };
+
+    let res = |ident: Ident, owner_id: OwnerId| {
+        if ident.name == name {
+            let def_id = owner_id.to_def_id();
+            Some(Res::Def(tcx.def_kind(def_id), def_id))
+        } else {
+            None
         }
+    };
+
+    match item_kind {
+        ItemKind::Mod(r#mod) => r#mod
+            .item_ids
+            .iter()
+            .filter_map(|&item_id| res(hir.item(item_id).ident, item_id.owner_id))
+            .collect(),
+        ItemKind::Impl(r#impl) => r#impl
+            .items
+            .iter()
+            .filter_map(|&ImplItemRef { ident, id, .. }| res(ident, id.owner_id))
+            .collect(),
+        ItemKind::Trait(.., trait_item_refs) => trait_item_refs
+            .iter()
+            .filter_map(|&TraitItemRef { ident, id, .. }| res(ident, id.owner_id))
+            .collect(),
+        _ => Vec::new(),
     }
+}
+
+fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> {
+    if let Some(local_id) = def_id.as_local() {
+        local_item_children_by_name(tcx, local_id, name)
+    } else {
+        non_local_item_children_by_name(tcx, def_id, name)
+    }
+}
 
-    fn find_crate(tcx: TyCtxt<'_>, name: &str) -> Option<DefId> {
+/// Resolves a def path like `std::vec::Vec`.
+///
+/// Can return multiple resolutions when there are multiple versions of the same crate, e.g.
+/// `memchr::memchr` could return the functions from both memchr 1.0 and memchr 2.0.
+///
+/// Also returns multiple results when there are mulitple paths under the same name e.g. `std::vec`
+/// would have both a [`DefKind::Mod`] and [`DefKind::Macro`].
+///
+/// This function is expensive and should be used sparingly.
+pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Vec<Res> {
+    fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator<Item = DefId> + '_ {
         tcx.crates(())
             .iter()
             .copied()
-            .find(|&num| tcx.crate_name(num).as_str() == name)
+            .filter(move |&num| tcx.crate_name(num) == name)
             .map(CrateNum::as_def_id)
     }
 
-    let (base, path) = match *path {
+    let tcx = cx.tcx;
+
+    let (base, mut path) = match *path {
         [primitive] => {
-            return PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy);
+            return vec![PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy)];
         },
         [base, ref path @ ..] => (base, path),
-        _ => return Res::Err,
+        _ => return Vec::new(),
     };
-    let tcx = cx.tcx;
-    let starts = find_primitive(tcx, base)
-        .chain(find_crate(tcx, base))
+
+    let base_sym = Symbol::intern(base);
+
+    let local_crate = if tcx.crate_name(LOCAL_CRATE) == base_sym {
+        Some(LOCAL_CRATE.as_def_id())
+    } else {
+        None
+    };
+
+    let starts = find_primitive_impls(tcx, base)
+        .chain(find_crates(tcx, base_sym))
+        .chain(local_crate)
         .map(|id| Res::Def(tcx.def_kind(id), id));
 
-    for first in starts {
-        let last = path
-            .iter()
-            .copied()
-            .enumerate()
-            // for each segment, find the child item
-            .try_fold(first, |res, (idx, segment)| {
-                let matches_ns = |res: Res| {
-                    // If at the last segment in the path, respect the namespace hint
-                    if idx == path.len() - 1 {
-                        match namespace_hint {
-                            Some(ns) => res.matches_ns(ns),
-                            None => true,
-                        }
-                    } else {
-                        res.matches_ns(Namespace::TypeNS)
-                    }
-                };
-
-                let def_id = res.def_id();
-                if let Some(item) = item_child_by_name(tcx, def_id, segment, matches_ns) {
-                    Some(item)
-                } else if matches!(res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
-                    // it is not a child item so check inherent impl items
-                    tcx.inherent_impls(def_id)
-                        .iter()
-                        .find_map(|&impl_def_id| item_child_by_name(tcx, impl_def_id, segment, matches_ns))
-                } else {
-                    None
-                }
-            });
+    let mut resolutions: Vec<Res> = starts.collect();
 
-        if let Some(last) = last {
-            return last;
-        }
+    while let [segment, rest @ ..] = path {
+        path = rest;
+        let segment = Symbol::intern(segment);
+
+        resolutions = resolutions
+            .into_iter()
+            .filter_map(|res| res.opt_def_id())
+            .flat_map(|def_id| {
+                // When the current def_id is e.g. `struct S`, check the impl items in
+                // `impl S { ... }`
+                let inherent_impl_children = tcx
+                    .inherent_impls(def_id)
+                    .iter()
+                    .flat_map(|&impl_def_id| item_children_by_name(tcx, impl_def_id, segment));
+
+                let direct_children = item_children_by_name(tcx, def_id, segment);
+
+                inherent_impl_children.chain(direct_children)
+            })
+            .collect();
     }
 
-    Res::Err
+    resolutions
+}
+
+/// Resolves a def path like `std::vec::Vec` to its [`DefId`]s, see [`def_path_res`].
+pub fn def_path_def_ids(cx: &LateContext<'_>, path: &[&str]) -> impl Iterator<Item = DefId> {
+    def_path_res(cx, path).into_iter().filter_map(|res| res.opt_def_id())
 }
 
 /// Convenience function to get the `DefId` of a trait by path.
@@ -661,10 +707,10 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str], namespace_hint: Option<
 ///
 /// This function is expensive and should be used sparingly.
 pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> {
-    match def_path_res(cx, path, Some(Namespace::TypeNS)) {
+    def_path_res(cx, path).into_iter().find_map(|res| match res {
         Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id),
         _ => None,
-    }
+    })
 }
 
 /// Gets the `hir::TraitRef` of the trait the given method is implemented for.
@@ -784,9 +830,9 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<
         if method.ident.name == sym::new {
             if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
                 if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() {
-                    return std_types_symbols
-                        .iter()
-                        .any(|&symbol| cx.tcx.is_diagnostic_item(symbol, adt.did()) || Some(adt.did()) == cx.tcx.lang_items().string());
+                    return std_types_symbols.iter().any(|&symbol| {
+                        cx.tcx.is_diagnostic_item(symbol, adt.did()) || Some(adt.did()) == cx.tcx.lang_items().string()
+                    });
                 }
             }
         }
@@ -963,7 +1009,7 @@ impl std::ops::BitOrAssign for CaptureKind {
 /// Note as this will walk up to parent expressions until the capture can be determined it should
 /// only be used while making a closure somewhere a value is consumed. e.g. a block, match arm, or
 /// function argument (other than a receiver).
-pub fn capture_local_usage<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'_>) -> CaptureKind {
+pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
     fn pat_capture_kind(cx: &LateContext<'_>, pat: &Pat<'_>) -> CaptureKind {
         let mut capture = CaptureKind::Ref(Mutability::Not);
         pat.each_binding_or_first(&mut |_, id, span, _| match cx
@@ -1260,23 +1306,6 @@ pub fn contains_return(expr: &hir::Expr<'_>) -> bool {
     .is_some()
 }
 
-/// Extends the span to the beginning of the spans line, incl. whitespaces.
-///
-/// ```rust
-///        let x = ();
-/// //             ^^
-/// // will be converted to
-///        let x = ();
-/// // ^^^^^^^^^^^^^^
-/// ```
-fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
-    let span = original_sp(span, DUMMY_SP);
-    let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap();
-    let line_no = source_map_and_line.line;
-    let line_start = source_map_and_line.sf.lines(|lines| lines[line_no]);
-    span.with_lo(line_start)
-}
-
 /// Gets the parent node, if any.
 pub fn get_parent_node(tcx: TyCtxt<'_>, id: HirId) -> Option<Node<'_>> {
     tcx.hir().parent_iter(id).next().map(|(_, node)| node)
@@ -1749,6 +1778,10 @@ pub fn has_attr(attrs: &[ast::Attribute], symbol: Symbol) -> bool {
     attrs.iter().any(|attr| attr.has_name(symbol))
 }
 
+pub fn has_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
+    has_attr(cx.tcx.hir().attrs(hir_id), sym::repr)
+}
+
 pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool {
     let map = &tcx.hir();
     let mut prev_enclosing_node = None;
@@ -1821,7 +1854,7 @@ pub fn match_any_def_paths(cx: &LateContext<'_>, did: DefId, paths: &[&[&str]])
 }
 
 /// Checks if the given `DefId` matches the path.
-pub fn match_def_path<'tcx>(cx: &LateContext<'tcx>, did: DefId, syms: &[&str]) -> bool {
+pub fn match_def_path(cx: &LateContext<'_>, did: DefId, syms: &[&str]) -> bool {
     // We should probably move to Symbols in Clippy as well rather than interning every time.
     let path = cx.get_def_path(did);
     syms.iter().map(|x| Symbol::intern(x)).eq(path.iter().copied())
@@ -1870,7 +1903,11 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
 
 /// Checks if the given function kind is an async function.
 pub fn is_async_fn(kind: FnKind<'_>) -> bool {
-    matches!(kind, FnKind::ItemFn(_, _, header) if header.asyncness.is_async())
+    match kind {
+        FnKind::ItemFn(_, _, header) => header.asyncness == IsAsync::Async,
+        FnKind::Method(_, sig) => sig.header.asyncness == IsAsync::Async,
+        FnKind::Closure => false,
+    }
 }
 
 /// Peels away all the compiler generated code surrounding the body of an async function,
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index 8b843732a23..79b19e6fb3e 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -12,13 +12,14 @@ macro_rules! msrv_aliases {
 
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
+    1,65,0 { LET_ELSE }
     1,62,0 { BOOL_THEN_SOME }
     1,58,0 { FORMAT_ARGS_CAPTURE }
     1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR }
     1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
-    1,51,0 { BORROW_AS_PTR, UNSIGNED_ABS }
+    1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS }
     1,50,0 { BOOL_THEN, CLAMP }
-    1,47,0 { TAU }
+    1,47,0 { TAU, IS_ASCII_DIGIT_CONST }
     1,46,0 { CONST_IF_MATCH }
     1,45,0 { STR_STRIP_PREFIX }
     1,43,0 { LOG2_10, LOG10_2 }
@@ -37,4 +38,5 @@ msrv_aliases! {
     1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN }
     1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR }
     1,16,0 { STR_REPEAT }
+    1,55,0 { SEEK_REWIND }
 }
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index bc851473430..6c09c146082 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -115,6 +115,9 @@ pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"];
 pub const STDOUT: [&str; 4] = ["std", "io", "stdio", "stdout"];
 pub const CONVERT_IDENTITY: [&str; 3] = ["core", "convert", "identity"];
 pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"];
+pub const STD_IO_SEEK: [&str; 3] = ["std", "io", "Seek"];
+pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
+pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
 pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
 pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
 pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 45b63a4aa5d..d183e28f667 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -18,7 +18,7 @@ use std::borrow::Cow;
 
 type McfResult = Result<(), (Span, Cow<'static, str>)>;
 
-pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv: Option<RustcVersion>) -> McfResult {
+pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: Option<RustcVersion>) -> McfResult {
     let def_id = body.source.def_id();
     let mut current = def_id;
     loop {
@@ -37,6 +37,7 @@ pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv:
                 ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"),
                 ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"),
                 ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {predicate:#?}"),
+                ty::PredicateKind::Ambiguous => panic!("ambiguous predicate on function: {predicate:#?}"),
             }
         }
         match predicates.parent {
@@ -276,9 +277,9 @@ fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &B
     Ok(())
 }
 
-fn check_terminator<'a, 'tcx>(
+fn check_terminator<'tcx>(
     tcx: TyCtxt<'tcx>,
-    body: &'a Body<'tcx>,
+    body: &Body<'tcx>,
     terminator: &Terminator<'tcx>,
     msrv: Option<RustcVersion>,
 ) -> McfResult {
diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs
index d28bd92d708..eacfa91ba55 100644
--- a/src/tools/clippy/clippy_utils/src/source.rs
+++ b/src/tools/clippy/clippy_utils/src/source.rs
@@ -2,13 +2,12 @@
 
 #![allow(clippy::module_name_repetitions)]
 
-use crate::line_span;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LintContext};
 use rustc_span::hygiene;
-use rustc_span::source_map::SourceMap;
-use rustc_span::{BytePos, Pos, Span, SpanData, SyntaxContext};
+use rustc_span::source_map::{original_sp, SourceMap};
+use rustc_span::{BytePos, Pos, Span, SpanData, SyntaxContext, DUMMY_SP};
 use std::borrow::Cow;
 
 /// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
@@ -55,6 +54,23 @@ fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePo
     })
 }
 
+/// Extends the span to the beginning of the spans line, incl. whitespaces.
+///
+/// ```rust
+///        let x = ();
+/// //             ^^
+/// // will be converted to
+///        let x = ();
+/// // ^^^^^^^^^^^^^^
+/// ```
+fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
+    let span = original_sp(span, DUMMY_SP);
+    let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap();
+    let line_no = source_map_and_line.line;
+    let line_start = source_map_and_line.sf.lines(|lines| lines[line_no]);
+    span.with_lo(line_start)
+}
+
 /// Returns the indentation of the line of a span
 ///
 /// ```rust,ignore
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index eefba8cd29c..3cacdb49377 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -801,7 +801,7 @@ pub struct DerefClosure {
 /// Returns `None` if no such use cases have been triggered in closure body
 ///
 /// note: this only works on single line immutable closures with exactly one input parameter.
-pub fn deref_closure_args<'tcx>(cx: &LateContext<'_>, closure: &'tcx hir::Expr<'_>) -> Option<DerefClosure> {
+pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Option<DerefClosure> {
     if let hir::ExprKind::Closure(&Closure { fn_decl, body, .. }) = closure.kind {
         let closure_body = cx.tcx.hir().body(body);
         // is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`)
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 5ec6f29fe91..8284dc5c28c 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -13,8 +13,9 @@ use rustc_infer::infer::{TyCtxtInferExt, type_variable::{TypeVariableOrigin, Typ
 use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::{ConstValue, Scalar};
 use rustc_middle::ty::{
-    self, AdtDef, Binder, BoundRegion, DefIdTree, FnSig, IntTy, ParamEnv, Predicate, PredicateKind, ProjectionTy,
-    Region, RegionKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy, VariantDef, VariantDiscr,
+    self, AdtDef, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, IntTy, List, ParamEnv, Predicate, PredicateKind,
+    ProjectionTy, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
+    VariantDef, VariantDiscr,
 };
 use rustc_middle::ty::{GenericArg, GenericArgKind};
 use rustc_span::symbol::Ident;
@@ -59,29 +60,64 @@ pub fn contains_adt_constructor<'tcx>(ty: Ty<'tcx>, adt: AdtDef<'tcx>) -> bool {
     })
 }
 
+/// Walks into `ty` and returns `true` if any inner type is an instance of the given type, or adt
+/// constructor of the same type.
+///
+/// This method also recurses into opaque type predicates, so call it with `impl Trait<U>` and `U`
+/// will also return `true`.
+pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, needle: Ty<'tcx>) -> bool {
+    ty.walk().any(|inner| match inner.unpack() {
+        GenericArgKind::Type(inner_ty) => {
+            if inner_ty == needle {
+                return true;
+            }
+
+            if inner_ty.ty_adt_def() == needle.ty_adt_def() {
+                return true;
+            }
+
+            if let ty::Opaque(def_id, _) = *inner_ty.kind() {
+                for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
+                    match predicate.kind().skip_binder() {
+                        // For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
+                        // and check substituions to find `U`.
+                        ty::PredicateKind::Trait(trait_predicate) => {
+                            if trait_predicate
+                                .trait_ref
+                                .substs
+                                .types()
+                                .skip(1) // Skip the implicit `Self` generic parameter
+                                .any(|ty| contains_ty_adt_constructor_opaque(cx, ty, needle))
+                            {
+                                return true;
+                            }
+                        },
+                        // For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
+                        // so we check the term for `U`.
+                        ty::PredicateKind::Projection(projection_predicate) => {
+                            if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() {
+                                if contains_ty_adt_constructor_opaque(cx, ty, needle) {
+                                    return true;
+                                }
+                            };
+                        },
+                        _ => (),
+                    }
+                }
+            }
+
+            false
+        },
+        GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
+    })
+}
+
 /// Resolves `<T as Iterator>::Item` for `T`
 /// Do not invoke without first verifying that the type implements `Iterator`
 pub fn get_iterator_item_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
     cx.tcx
         .get_diagnostic_item(sym::Iterator)
-        .and_then(|iter_did| get_associated_type(cx, ty, iter_did, "Item"))
-}
-
-/// Returns the associated type `name` for `ty` as an implementation of `trait_id`.
-/// Do not invoke without first verifying that the type implements the trait.
-pub fn get_associated_type<'tcx>(
-    cx: &LateContext<'tcx>,
-    ty: Ty<'tcx>,
-    trait_id: DefId,
-    name: &str,
-) -> Option<Ty<'tcx>> {
-    cx.tcx
-        .associated_items(trait_id)
-        .find_by_name_and_kind(cx.tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id)
-        .and_then(|assoc| {
-            let proj = cx.tcx.mk_projection(assoc.def_id, cx.tcx.mk_substs_trait(ty, []));
-            cx.tcx.try_normalize_erasing_regions(cx.param_env, proj).ok()
-        })
+        .and_then(|iter_did| cx.get_associated_type(ty, iter_did, "Item"))
 }
 
 /// Get the diagnostic name of a type, e.g. `sym::HashMap`. To check if a type
@@ -705,7 +741,7 @@ impl core::ops::Add<u32> for EnumValue {
     }
 }
 
-/// Attempts to read the given constant as though it were an an enum value.
+/// Attempts to read the given constant as though it were an enum value.
 #[expect(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
 pub fn read_explicit_enum_value(tcx: TyCtxt<'_>, id: DefId) -> Option<EnumValue> {
     if let Ok(ConstValue::Scalar(Scalar::Int(value))) = tcx.const_eval_poly(id) {
@@ -786,6 +822,42 @@ pub fn for_each_top_level_late_bound_region<B>(
     ty.visit_with(&mut V { index: 0, f })
 }
 
+pub struct AdtVariantInfo {
+    pub ind: usize,
+    pub size: u64,
+
+    /// (ind, size)
+    pub fields_size: Vec<(usize, u64)>,
+}
+
+impl AdtVariantInfo {
+    /// Returns ADT variants ordered by size
+    pub fn new<'tcx>(cx: &LateContext<'tcx>, adt: AdtDef<'tcx>, subst: &'tcx List<GenericArg<'tcx>>) -> Vec<Self> {
+        let mut variants_size = adt
+            .variants()
+            .iter()
+            .enumerate()
+            .map(|(i, variant)| {
+                let mut fields_size = variant
+                    .fields
+                    .iter()
+                    .enumerate()
+                    .map(|(i, f)| (i, approx_ty_size(cx, f.ty(cx.tcx, subst))))
+                    .collect::<Vec<_>>();
+                fields_size.sort_by(|(_, a_size), (_, b_size)| (a_size.cmp(b_size)));
+
+                Self {
+                    ind: i,
+                    size: fields_size.iter().map(|(_, size)| size).sum(),
+                    fields_size,
+                }
+            })
+            .collect::<Vec<_>>();
+        variants_size.sort_by(|a, b| (b.size.cmp(&a.size)));
+        variants_size
+    }
+}
+
 /// Gets the struct or enum variant from the given `Res`
 pub fn variant_of_res<'tcx>(cx: &LateContext<'tcx>, res: Res) -> Option<&'tcx VariantDef> {
     match res {
@@ -880,3 +952,132 @@ pub fn approx_ty_size<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> u64 {
         (Err(_), _) => 0,
     }
 }
+
+/// Makes the projection type for the named associated type in the given impl or trait impl.
+///
+/// This function is for associated types which are "known" to exist, and as such, will only return
+/// `None` when debug assertions are disabled in order to prevent ICE's. With debug assertions
+/// enabled this will check that the named associated type exists, the correct number of
+/// substitutions are given, and that the correct kinds of substitutions are given (lifetime,
+/// constant or type). This will not check if type normalization would succeed.
+pub fn make_projection<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    container_id: DefId,
+    assoc_ty: Symbol,
+    substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+) -> Option<ProjectionTy<'tcx>> {
+    fn helper<'tcx>(
+        tcx: TyCtxt<'tcx>,
+        container_id: DefId,
+        assoc_ty: Symbol,
+        substs: SubstsRef<'tcx>,
+    ) -> Option<ProjectionTy<'tcx>> {
+        let Some(assoc_item) = tcx
+            .associated_items(container_id)
+            .find_by_name_and_kind(tcx, Ident::with_dummy_span(assoc_ty), AssocKind::Type, container_id)
+        else {
+            debug_assert!(false, "type `{assoc_ty}` not found in `{container_id:?}`");
+            return None;
+        };
+        #[cfg(debug_assertions)]
+        {
+            let generics = tcx.generics_of(assoc_item.def_id);
+            let generic_count = generics.parent_count + generics.params.len();
+            let params = generics
+                .parent
+                .map_or([].as_slice(), |id| &*tcx.generics_of(id).params)
+                .iter()
+                .chain(&generics.params)
+                .map(|x| &x.kind);
+
+            debug_assert!(
+                generic_count == substs.len(),
+                "wrong number of substs for `{:?}`: found `{}` expected `{}`.\n\
+                    note: the expected parameters are: {:#?}\n\
+                    the given arguments are: `{:#?}`",
+                assoc_item.def_id,
+                substs.len(),
+                generic_count,
+                params.map(ty::GenericParamDefKind::descr).collect::<Vec<_>>(),
+                substs,
+            );
+
+            if let Some((idx, (param, arg))) = params
+                .clone()
+                .zip(substs.iter().map(GenericArg::unpack))
+                .enumerate()
+                .find(|(_, (param, arg))| {
+                    !matches!(
+                        (param, arg),
+                        (ty::GenericParamDefKind::Lifetime, GenericArgKind::Lifetime(_))
+                            | (ty::GenericParamDefKind::Type { .. }, GenericArgKind::Type(_))
+                            | (ty::GenericParamDefKind::Const { .. }, GenericArgKind::Const(_))
+                    )
+                })
+            {
+                debug_assert!(
+                    false,
+                    "mismatched subst type at index {}: expected a {}, found `{:?}`\n\
+                        note: the expected parameters are {:#?}\n\
+                        the given arguments are {:#?}",
+                    idx,
+                    param.descr(),
+                    arg,
+                    params.map(ty::GenericParamDefKind::descr).collect::<Vec<_>>(),
+                    substs,
+                );
+            }
+        }
+
+        Some(ProjectionTy {
+            substs,
+            item_def_id: assoc_item.def_id,
+        })
+    }
+    helper(
+        tcx,
+        container_id,
+        assoc_ty,
+        tcx.mk_substs(substs.into_iter().map(Into::into)),
+    )
+}
+
+/// Normalizes the named associated type in the given impl or trait impl.
+///
+/// This function is for associated types which are "known" to be valid with the given
+/// substitutions, and as such, will only return `None` when debug assertions are disabled in order
+/// to prevent ICE's. With debug assertions enabled this will check that that type normalization
+/// succeeds as well as everything checked by `make_projection`.
+pub fn make_normalized_projection<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ParamEnv<'tcx>,
+    container_id: DefId,
+    assoc_ty: Symbol,
+    substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+) -> Option<Ty<'tcx>> {
+    fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: ProjectionTy<'tcx>) -> Option<Ty<'tcx>> {
+        #[cfg(debug_assertions)]
+        if let Some((i, subst)) = ty
+            .substs
+            .iter()
+            .enumerate()
+            .find(|(_, subst)| subst.has_late_bound_regions())
+        {
+            debug_assert!(
+                false,
+                "substs contain late-bound region at index `{i}` which can't be normalized.\n\
+                    use `TyCtxt::erase_late_bound_regions`\n\
+                    note: subst is `{subst:#?}`",
+            );
+            return None;
+        }
+        match tcx.try_normalize_erasing_regions(param_env, tcx.mk_projection(ty.item_def_id, ty.substs)) {
+            Ok(ty) => Some(ty),
+            Err(e) => {
+                debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}");
+                None
+            },
+        }
+    }
+    helper(tcx, param_env, make_projection(tcx, container_id, assoc_ty, substs)?)
+}
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index 000fb51c018..797722cfc1f 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -73,12 +73,7 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
         self.update(cmt);
     }
 
-    fn fake_read(
-        &mut self,
-        _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>,
-        _: FakeReadCause,
-        _: HirId,
-    ) {}
+    fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
 }
 
 pub struct ParamBindingIdCollector {
diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml
new file mode 100644
index 00000000000..082570f1fe5
--- /dev/null
+++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "declare_clippy_lint"
+version = "0.1.67"
+edition = "2021"
+publish = false
+
+[lib]
+proc-macro = true
+
+[dependencies]
+itertools = "0.10.1"
+quote = "1.0.21"
+syn = "1.0.100"
+
+[features]
+deny-warnings = []
diff --git a/src/tools/clippy/declare_clippy_lint/src/lib.rs b/src/tools/clippy/declare_clippy_lint/src/lib.rs
new file mode 100644
index 00000000000..26210556d65
--- /dev/null
+++ b/src/tools/clippy/declare_clippy_lint/src/lib.rs
@@ -0,0 +1,175 @@
+#![feature(let_chains)]
+#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+// warn on lints, that are included in `rust-lang/rust`s bootstrap
+#![warn(rust_2018_idioms, unused_lifetimes)]
+
+use proc_macro::TokenStream;
+use quote::{format_ident, quote};
+use syn::parse::{Parse, ParseStream};
+use syn::{parse_macro_input, Attribute, Error, Ident, Lit, LitStr, Meta, Result, Token};
+
+fn parse_attr<const LEN: usize>(path: [&'static str; LEN], attr: &Attribute) -> Option<LitStr> {
+    if let Meta::NameValue(name_value) = attr.parse_meta().ok()? {
+        let path_idents = name_value.path.segments.iter().map(|segment| &segment.ident);
+
+        if itertools::equal(path_idents, path)
+            && let Lit::Str(lit) = name_value.lit
+        {
+            return Some(lit);
+        }
+    }
+
+    None
+}
+
+struct ClippyLint {
+    attrs: Vec<Attribute>,
+    explanation: String,
+    name: Ident,
+    category: Ident,
+    description: LitStr,
+}
+
+impl Parse for ClippyLint {
+    fn parse(input: ParseStream<'_>) -> Result<Self> {
+        let attrs = input.call(Attribute::parse_outer)?;
+
+        let mut in_code = false;
+        let mut explanation = String::new();
+        let mut version = None;
+        for attr in &attrs {
+            if let Some(lit) = parse_attr(["doc"], attr) {
+                let value = lit.value();
+                let line = value.strip_prefix(' ').unwrap_or(&value);
+
+                if line.starts_with("```") {
+                    explanation += "```\n";
+                    in_code = !in_code;
+                } else if !(in_code && line.starts_with("# ")) {
+                    explanation += line;
+                    explanation.push('\n');
+                }
+            } else if let Some(lit) = parse_attr(["clippy", "version"], attr) {
+                if let Some(duplicate) = version.replace(lit) {
+                    return Err(Error::new_spanned(duplicate, "duplicate clippy::version"));
+                }
+            } else {
+                return Err(Error::new_spanned(attr, "unexpected attribute"));
+            }
+        }
+
+        input.parse::<Token![pub]>()?;
+        let name = input.parse()?;
+        input.parse::<Token![,]>()?;
+
+        let category = input.parse()?;
+        input.parse::<Token![,]>()?;
+
+        let description = input.parse()?;
+
+        Ok(Self {
+            attrs,
+            explanation,
+            name,
+            category,
+            description,
+        })
+    }
+}
+
+/// Macro used to declare a Clippy lint.
+///
+/// Every lint declaration consists of 4 parts:
+///
+/// 1. The documentation, which is used for the website and `cargo clippy --explain`
+/// 2. The `LINT_NAME`. See [lint naming][lint_naming] on lint naming conventions.
+/// 3. The `lint_level`, which is a mapping from *one* of our lint groups to `Allow`, `Warn` or
+///    `Deny`. The lint level here has nothing to do with what lint groups the lint is a part of.
+/// 4. The `description` that contains a short explanation on what's wrong with code where the
+///    lint is triggered.
+///
+/// Currently the categories `style`, `correctness`, `suspicious`, `complexity` and `perf` are
+/// enabled by default. As said in the README.md of this repository, if the lint level mapping
+/// changes, please update README.md.
+///
+/// # Example
+///
+/// ```
+/// use rustc_session::declare_tool_lint;
+///
+/// declare_clippy_lint! {
+///     /// ### What it does
+///     /// Checks for ... (describe what the lint matches).
+///     ///
+///     /// ### Why is this bad?
+///     /// Supply the reason for linting the code.
+///     ///
+///     /// ### Example
+///     /// ```rust
+///     /// Insert a short example of code that triggers the lint
+///     /// ```
+///     ///
+///     /// Use instead:
+///     /// ```rust
+///     /// Insert a short example of improved code that doesn't trigger the lint
+///     /// ```
+///     #[clippy::version = "1.65.0"]
+///     pub LINT_NAME,
+///     pedantic,
+///     "description"
+/// }
+/// ```
+/// [lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
+#[proc_macro]
+pub fn declare_clippy_lint(input: TokenStream) -> TokenStream {
+    let ClippyLint {
+        attrs,
+        explanation,
+        name,
+        category,
+        description,
+    } = parse_macro_input!(input as ClippyLint);
+
+    let mut category = category.to_string();
+
+    let level = format_ident!(
+        "{}",
+        match category.as_str() {
+            "correctness" => "Deny",
+            "style" | "suspicious" | "complexity" | "perf" | "internal_warn" => "Warn",
+            "pedantic" | "restriction" | "cargo" | "nursery" | "internal" => "Allow",
+            _ => panic!("unknown category {category}"),
+        },
+    );
+
+    let info = if category == "internal_warn" {
+        None
+    } else {
+        let info_name = format_ident!("{name}_INFO");
+
+        (&mut category[0..1]).make_ascii_uppercase();
+        let category_variant = format_ident!("{category}");
+
+        Some(quote! {
+            pub(crate) static #info_name: &'static crate::LintInfo = &crate::LintInfo {
+                lint: &#name,
+                category: crate::LintCategory::#category_variant,
+                explanation: #explanation,
+            };
+        })
+    };
+
+    let output = quote! {
+        declare_tool_lint! {
+            #(#attrs)*
+            pub clippy::#name,
+            #level,
+            #description,
+            report_in_external_macro: true
+        }
+
+        #info
+    };
+
+    TokenStream::from(output)
+}
diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs
index 54c1b80c42d..ee8ab7c1d7c 100644
--- a/src/tools/clippy/lintcheck/src/main.rs
+++ b/src/tools/clippy/lintcheck/src/main.rs
@@ -544,34 +544,6 @@ fn gather_stats(clippy_warnings: &[ClippyWarning]) -> (String, HashMap<&String,
     (stats_string, counter)
 }
 
-/// check if the latest modification of the logfile is older than the modification date of the
-/// clippy binary, if this is true, we should clean the lintchec shared target directory and recheck
-fn lintcheck_needs_rerun(lintcheck_logs_path: &Path, paths: [&Path; 2]) -> bool {
-    if !lintcheck_logs_path.exists() {
-        return true;
-    }
-
-    let clippy_modified: std::time::SystemTime = {
-        let [cargo, driver] = paths.map(|p| {
-            std::fs::metadata(p)
-                .expect("failed to get metadata of file")
-                .modified()
-                .expect("failed to get modification date")
-        });
-        // the oldest modification of either of the binaries
-        std::cmp::max(cargo, driver)
-    };
-
-    let logs_modified: std::time::SystemTime = std::fs::metadata(lintcheck_logs_path)
-        .expect("failed to get metadata of file")
-        .modified()
-        .expect("failed to get modification date");
-
-    // time is represented in seconds since X
-    // logs_modified 2 and clippy_modified 5 means clippy binary is older and we need to recheck
-    logs_modified < clippy_modified
-}
-
 #[allow(clippy::too_many_lines)]
 fn main() {
     // We're being executed as a `RUSTC_WRAPPER` as part of `--recursive`
@@ -594,23 +566,6 @@ fn main() {
     let cargo_clippy_path = fs::canonicalize(format!("target/debug/cargo-clippy{EXE_SUFFIX}")).unwrap();
     let clippy_driver_path = fs::canonicalize(format!("target/debug/clippy-driver{EXE_SUFFIX}")).unwrap();
 
-    // if the clippy bin is newer than our logs, throw away target dirs to force clippy to
-    // refresh the logs
-    if lintcheck_needs_rerun(
-        &config.lintcheck_results_path,
-        [&cargo_clippy_path, &clippy_driver_path],
-    ) {
-        let shared_target_dir = "target/lintcheck/shared_target_dir";
-        // if we get an Err here, the shared target dir probably does simply not exist
-        if let Ok(metadata) = std::fs::metadata(shared_target_dir) {
-            if metadata.is_dir() {
-                println!("Clippy is newer than lint check logs, clearing lintcheck shared target dir...");
-                std::fs::remove_dir_all(shared_target_dir)
-                    .expect("failed to remove target/lintcheck/shared_target_dir");
-            }
-        }
-    }
-
     // assert that clippy is found
     assert!(
         cargo_clippy_path.is_file(),
@@ -678,7 +633,7 @@ fn main() {
         .unwrap();
 
     let server = config.recursive.then(|| {
-        fs::remove_dir_all("target/lintcheck/shared_target_dir/recursive").unwrap_or_default();
+        let _ = fs::remove_dir_all("target/lintcheck/shared_target_dir/recursive");
 
         LintcheckServer::spawn(recursive_options)
     });
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 748d8a31716..a806c156479 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2022-10-20"
-components = ["cargo", "llvm-tools-preview", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
+channel = "nightly-2022-11-21"
+components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/src/docs.rs b/src/tools/clippy/src/docs.rs
deleted file mode 100644
index c033ad294a3..00000000000
--- a/src/tools/clippy/src/docs.rs
+++ /dev/null
@@ -1,606 +0,0 @@
-// autogenerated. Please look at /clippy_dev/src/update_lints.rs
-
-macro_rules! include_lint {
-    ($file_name: expr) => {
-        include_str!($file_name)
-    };
-}
-
-macro_rules! docs {
-    ($($lint_name: expr,)*) => {
-        pub fn explain(lint: &str) {
-            println!("{}", match lint {
-                $(
-                    $lint_name => include_lint!(concat!("docs/", concat!($lint_name, ".txt"))),
-                )*
-                _ => "unknown lint",
-            })
-        }
-    }
-}
-
-docs! {
-    "absurd_extreme_comparisons",
-    "alloc_instead_of_core",
-    "allow_attributes_without_reason",
-    "almost_complete_letter_range",
-    "almost_swapped",
-    "approx_constant",
-    "arithmetic_side_effects",
-    "as_conversions",
-    "as_ptr_cast_mut",
-    "as_underscore",
-    "assertions_on_constants",
-    "assertions_on_result_states",
-    "assign_op_pattern",
-    "async_yields_async",
-    "await_holding_invalid_type",
-    "await_holding_lock",
-    "await_holding_refcell_ref",
-    "bad_bit_mask",
-    "bind_instead_of_map",
-    "blanket_clippy_restriction_lints",
-    "blocks_in_if_conditions",
-    "bool_assert_comparison",
-    "bool_comparison",
-    "bool_to_int_with_if",
-    "borrow_as_ptr",
-    "borrow_deref_ref",
-    "borrow_interior_mutable_const",
-    "borrowed_box",
-    "box_collection",
-    "box_default",
-    "boxed_local",
-    "branches_sharing_code",
-    "builtin_type_shadow",
-    "bytes_count_to_len",
-    "bytes_nth",
-    "cargo_common_metadata",
-    "case_sensitive_file_extension_comparisons",
-    "cast_abs_to_unsigned",
-    "cast_enum_constructor",
-    "cast_enum_truncation",
-    "cast_lossless",
-    "cast_nan_to_int",
-    "cast_possible_truncation",
-    "cast_possible_wrap",
-    "cast_precision_loss",
-    "cast_ptr_alignment",
-    "cast_ref_to_mut",
-    "cast_sign_loss",
-    "cast_slice_different_sizes",
-    "cast_slice_from_raw_parts",
-    "char_lit_as_u8",
-    "chars_last_cmp",
-    "chars_next_cmp",
-    "checked_conversions",
-    "clone_double_ref",
-    "clone_on_copy",
-    "clone_on_ref_ptr",
-    "cloned_instead_of_copied",
-    "cmp_nan",
-    "cmp_null",
-    "cmp_owned",
-    "cognitive_complexity",
-    "collapsible_else_if",
-    "collapsible_if",
-    "collapsible_match",
-    "collapsible_str_replace",
-    "comparison_chain",
-    "comparison_to_empty",
-    "copy_iterator",
-    "crate_in_macro_def",
-    "create_dir",
-    "crosspointer_transmute",
-    "dbg_macro",
-    "debug_assert_with_mut_call",
-    "decimal_literal_representation",
-    "declare_interior_mutable_const",
-    "default_instead_of_iter_empty",
-    "default_numeric_fallback",
-    "default_trait_access",
-    "default_union_representation",
-    "deprecated_cfg_attr",
-    "deprecated_semver",
-    "deref_addrof",
-    "deref_by_slicing",
-    "derivable_impls",
-    "derive_hash_xor_eq",
-    "derive_ord_xor_partial_ord",
-    "derive_partial_eq_without_eq",
-    "disallowed_macros",
-    "disallowed_methods",
-    "disallowed_names",
-    "disallowed_script_idents",
-    "disallowed_types",
-    "diverging_sub_expression",
-    "doc_link_with_quotes",
-    "doc_markdown",
-    "double_comparisons",
-    "double_must_use",
-    "double_neg",
-    "double_parens",
-    "drop_copy",
-    "drop_non_drop",
-    "drop_ref",
-    "duplicate_mod",
-    "duplicate_underscore_argument",
-    "duration_subsec",
-    "else_if_without_else",
-    "empty_drop",
-    "empty_enum",
-    "empty_line_after_outer_attr",
-    "empty_loop",
-    "empty_structs_with_brackets",
-    "enum_clike_unportable_variant",
-    "enum_glob_use",
-    "enum_variant_names",
-    "eq_op",
-    "equatable_if_let",
-    "erasing_op",
-    "err_expect",
-    "excessive_precision",
-    "exhaustive_enums",
-    "exhaustive_structs",
-    "exit",
-    "expect_fun_call",
-    "expect_used",
-    "expl_impl_clone_on_copy",
-    "explicit_auto_deref",
-    "explicit_counter_loop",
-    "explicit_deref_methods",
-    "explicit_into_iter_loop",
-    "explicit_iter_loop",
-    "explicit_write",
-    "extend_with_drain",
-    "extra_unused_lifetimes",
-    "fallible_impl_from",
-    "field_reassign_with_default",
-    "filetype_is_file",
-    "filter_map_identity",
-    "filter_map_next",
-    "filter_next",
-    "flat_map_identity",
-    "flat_map_option",
-    "float_arithmetic",
-    "float_cmp",
-    "float_cmp_const",
-    "float_equality_without_abs",
-    "fn_address_comparisons",
-    "fn_params_excessive_bools",
-    "fn_to_numeric_cast",
-    "fn_to_numeric_cast_any",
-    "fn_to_numeric_cast_with_truncation",
-    "for_kv_map",
-    "forget_copy",
-    "forget_non_drop",
-    "forget_ref",
-    "format_in_format_args",
-    "format_push_string",
-    "from_iter_instead_of_collect",
-    "from_over_into",
-    "from_str_radix_10",
-    "future_not_send",
-    "get_first",
-    "get_last_with_len",
-    "get_unwrap",
-    "identity_op",
-    "if_let_mutex",
-    "if_not_else",
-    "if_same_then_else",
-    "if_then_some_else_none",
-    "ifs_same_cond",
-    "implicit_clone",
-    "implicit_hasher",
-    "implicit_return",
-    "implicit_saturating_add",
-    "implicit_saturating_sub",
-    "imprecise_flops",
-    "inconsistent_digit_grouping",
-    "inconsistent_struct_constructor",
-    "index_refutable_slice",
-    "indexing_slicing",
-    "ineffective_bit_mask",
-    "inefficient_to_string",
-    "infallible_destructuring_match",
-    "infinite_iter",
-    "inherent_to_string",
-    "inherent_to_string_shadow_display",
-    "init_numbered_fields",
-    "inline_always",
-    "inline_asm_x86_att_syntax",
-    "inline_asm_x86_intel_syntax",
-    "inline_fn_without_body",
-    "inspect_for_each",
-    "int_plus_one",
-    "integer_arithmetic",
-    "integer_division",
-    "into_iter_on_ref",
-    "invalid_null_ptr_usage",
-    "invalid_regex",
-    "invalid_upcast_comparisons",
-    "invalid_utf8_in_unchecked",
-    "invisible_characters",
-    "is_digit_ascii_radix",
-    "items_after_statements",
-    "iter_cloned_collect",
-    "iter_count",
-    "iter_kv_map",
-    "iter_next_loop",
-    "iter_next_slice",
-    "iter_not_returning_iterator",
-    "iter_nth",
-    "iter_nth_zero",
-    "iter_on_empty_collections",
-    "iter_on_single_items",
-    "iter_overeager_cloned",
-    "iter_skip_next",
-    "iter_with_drain",
-    "iterator_step_by_zero",
-    "just_underscores_and_digits",
-    "large_const_arrays",
-    "large_digit_groups",
-    "large_enum_variant",
-    "large_include_file",
-    "large_stack_arrays",
-    "large_types_passed_by_value",
-    "len_without_is_empty",
-    "len_zero",
-    "let_and_return",
-    "let_underscore_drop",
-    "let_underscore_lock",
-    "let_underscore_must_use",
-    "let_unit_value",
-    "linkedlist",
-    "lossy_float_literal",
-    "macro_use_imports",
-    "main_recursion",
-    "manual_assert",
-    "manual_async_fn",
-    "manual_bits",
-    "manual_clamp",
-    "manual_filter",
-    "manual_filter_map",
-    "manual_find",
-    "manual_find_map",
-    "manual_flatten",
-    "manual_instant_elapsed",
-    "manual_map",
-    "manual_memcpy",
-    "manual_non_exhaustive",
-    "manual_ok_or",
-    "manual_range_contains",
-    "manual_rem_euclid",
-    "manual_retain",
-    "manual_saturating_arithmetic",
-    "manual_split_once",
-    "manual_str_repeat",
-    "manual_string_new",
-    "manual_strip",
-    "manual_swap",
-    "manual_unwrap_or",
-    "many_single_char_names",
-    "map_clone",
-    "map_collect_result_unit",
-    "map_entry",
-    "map_err_ignore",
-    "map_flatten",
-    "map_identity",
-    "map_unwrap_or",
-    "match_as_ref",
-    "match_bool",
-    "match_like_matches_macro",
-    "match_on_vec_items",
-    "match_overlapping_arm",
-    "match_ref_pats",
-    "match_result_ok",
-    "match_same_arms",
-    "match_single_binding",
-    "match_str_case_mismatch",
-    "match_wild_err_arm",
-    "match_wildcard_for_single_variants",
-    "maybe_infinite_iter",
-    "mem_forget",
-    "mem_replace_option_with_none",
-    "mem_replace_with_default",
-    "mem_replace_with_uninit",
-    "min_max",
-    "mismatched_target_os",
-    "mismatching_type_param_order",
-    "misrefactored_assign_op",
-    "missing_const_for_fn",
-    "missing_docs_in_private_items",
-    "missing_enforced_import_renames",
-    "missing_errors_doc",
-    "missing_inline_in_public_items",
-    "missing_panics_doc",
-    "missing_safety_doc",
-    "missing_spin_loop",
-    "missing_trait_methods",
-    "mistyped_literal_suffixes",
-    "mixed_case_hex_literals",
-    "mixed_read_write_in_expression",
-    "mod_module_files",
-    "module_inception",
-    "module_name_repetitions",
-    "modulo_arithmetic",
-    "modulo_one",
-    "multi_assignments",
-    "multiple_crate_versions",
-    "multiple_inherent_impl",
-    "must_use_candidate",
-    "must_use_unit",
-    "mut_from_ref",
-    "mut_mut",
-    "mut_mutex_lock",
-    "mut_range_bound",
-    "mutable_key_type",
-    "mutex_atomic",
-    "mutex_integer",
-    "naive_bytecount",
-    "needless_arbitrary_self_type",
-    "needless_bitwise_bool",
-    "needless_bool",
-    "needless_borrow",
-    "needless_borrowed_reference",
-    "needless_collect",
-    "needless_continue",
-    "needless_doctest_main",
-    "needless_for_each",
-    "needless_late_init",
-    "needless_lifetimes",
-    "needless_match",
-    "needless_option_as_deref",
-    "needless_option_take",
-    "needless_parens_on_range_literals",
-    "needless_pass_by_value",
-    "needless_question_mark",
-    "needless_range_loop",
-    "needless_return",
-    "needless_splitn",
-    "needless_update",
-    "neg_cmp_op_on_partial_ord",
-    "neg_multiply",
-    "negative_feature_names",
-    "never_loop",
-    "new_ret_no_self",
-    "new_without_default",
-    "no_effect",
-    "no_effect_replace",
-    "no_effect_underscore_binding",
-    "non_ascii_literal",
-    "non_octal_unix_permissions",
-    "non_send_fields_in_send_ty",
-    "nonminimal_bool",
-    "nonsensical_open_options",
-    "nonstandard_macro_braces",
-    "not_unsafe_ptr_arg_deref",
-    "obfuscated_if_else",
-    "octal_escapes",
-    "ok_expect",
-    "only_used_in_recursion",
-    "op_ref",
-    "option_as_ref_deref",
-    "option_env_unwrap",
-    "option_filter_map",
-    "option_if_let_else",
-    "option_map_or_none",
-    "option_map_unit_fn",
-    "option_option",
-    "or_fun_call",
-    "or_then_unwrap",
-    "out_of_bounds_indexing",
-    "overflow_check_conditional",
-    "overly_complex_bool_expr",
-    "panic",
-    "panic_in_result_fn",
-    "panicking_unwrap",
-    "partial_pub_fields",
-    "partialeq_ne_impl",
-    "partialeq_to_none",
-    "path_buf_push_overwrite",
-    "pattern_type_mismatch",
-    "possible_missing_comma",
-    "precedence",
-    "print_in_format_impl",
-    "print_literal",
-    "print_stderr",
-    "print_stdout",
-    "print_with_newline",
-    "println_empty_string",
-    "ptr_arg",
-    "ptr_as_ptr",
-    "ptr_eq",
-    "ptr_offset_with_cast",
-    "pub_use",
-    "question_mark",
-    "range_minus_one",
-    "range_plus_one",
-    "range_zip_with_len",
-    "rc_buffer",
-    "rc_clone_in_vec_init",
-    "rc_mutex",
-    "read_zero_byte_vec",
-    "recursive_format_impl",
-    "redundant_allocation",
-    "redundant_clone",
-    "redundant_closure",
-    "redundant_closure_call",
-    "redundant_closure_for_method_calls",
-    "redundant_else",
-    "redundant_feature_names",
-    "redundant_field_names",
-    "redundant_pattern",
-    "redundant_pattern_matching",
-    "redundant_pub_crate",
-    "redundant_slicing",
-    "redundant_static_lifetimes",
-    "ref_binding_to_reference",
-    "ref_option_ref",
-    "repeat_once",
-    "rest_pat_in_fully_bound_structs",
-    "result_large_err",
-    "result_map_or_into_option",
-    "result_map_unit_fn",
-    "result_unit_err",
-    "return_self_not_must_use",
-    "reversed_empty_ranges",
-    "same_functions_in_if_condition",
-    "same_item_push",
-    "same_name_method",
-    "search_is_some",
-    "self_assignment",
-    "self_named_constructors",
-    "self_named_module_files",
-    "semicolon_if_nothing_returned",
-    "separated_literal_suffix",
-    "serde_api_misuse",
-    "shadow_reuse",
-    "shadow_same",
-    "shadow_unrelated",
-    "short_circuit_statement",
-    "should_implement_trait",
-    "significant_drop_in_scrutinee",
-    "similar_names",
-    "single_char_add_str",
-    "single_char_lifetime_names",
-    "single_char_pattern",
-    "single_component_path_imports",
-    "single_element_loop",
-    "single_match",
-    "single_match_else",
-    "size_of_in_element_count",
-    "skip_while_next",
-    "slow_vector_initialization",
-    "stable_sort_primitive",
-    "std_instead_of_alloc",
-    "std_instead_of_core",
-    "str_to_string",
-    "string_add",
-    "string_add_assign",
-    "string_extend_chars",
-    "string_from_utf8_as_bytes",
-    "string_lit_as_bytes",
-    "string_slice",
-    "string_to_string",
-    "strlen_on_c_strings",
-    "struct_excessive_bools",
-    "suboptimal_flops",
-    "suspicious_arithmetic_impl",
-    "suspicious_assignment_formatting",
-    "suspicious_else_formatting",
-    "suspicious_map",
-    "suspicious_op_assign_impl",
-    "suspicious_operation_groupings",
-    "suspicious_splitn",
-    "suspicious_to_owned",
-    "suspicious_unary_op_formatting",
-    "swap_ptr_to_ref",
-    "tabs_in_doc_comments",
-    "temporary_assignment",
-    "to_digit_is_some",
-    "to_string_in_format_args",
-    "todo",
-    "too_many_arguments",
-    "too_many_lines",
-    "toplevel_ref_arg",
-    "trailing_empty_array",
-    "trait_duplication_in_bounds",
-    "transmute_bytes_to_str",
-    "transmute_float_to_int",
-    "transmute_int_to_bool",
-    "transmute_int_to_char",
-    "transmute_int_to_float",
-    "transmute_num_to_bytes",
-    "transmute_ptr_to_ptr",
-    "transmute_ptr_to_ref",
-    "transmute_undefined_repr",
-    "transmutes_expressible_as_ptr_casts",
-    "transmuting_null",
-    "trim_split_whitespace",
-    "trivial_regex",
-    "trivially_copy_pass_by_ref",
-    "try_err",
-    "type_complexity",
-    "type_repetition_in_bounds",
-    "undocumented_unsafe_blocks",
-    "undropped_manually_drops",
-    "unicode_not_nfc",
-    "unimplemented",
-    "uninit_assumed_init",
-    "uninit_vec",
-    "uninlined_format_args",
-    "unit_arg",
-    "unit_cmp",
-    "unit_hash",
-    "unit_return_expecting_ord",
-    "unnecessary_cast",
-    "unnecessary_filter_map",
-    "unnecessary_find_map",
-    "unnecessary_fold",
-    "unnecessary_join",
-    "unnecessary_lazy_evaluations",
-    "unnecessary_mut_passed",
-    "unnecessary_operation",
-    "unnecessary_owned_empty_strings",
-    "unnecessary_self_imports",
-    "unnecessary_sort_by",
-    "unnecessary_to_owned",
-    "unnecessary_unwrap",
-    "unnecessary_wraps",
-    "unneeded_field_pattern",
-    "unneeded_wildcard_pattern",
-    "unnested_or_patterns",
-    "unreachable",
-    "unreadable_literal",
-    "unsafe_derive_deserialize",
-    "unsafe_removed_from_name",
-    "unseparated_literal_suffix",
-    "unsound_collection_transmute",
-    "unused_async",
-    "unused_format_specs",
-    "unused_io_amount",
-    "unused_peekable",
-    "unused_rounding",
-    "unused_self",
-    "unused_unit",
-    "unusual_byte_groupings",
-    "unwrap_in_result",
-    "unwrap_or_else_default",
-    "unwrap_used",
-    "upper_case_acronyms",
-    "use_debug",
-    "use_self",
-    "used_underscore_binding",
-    "useless_asref",
-    "useless_attribute",
-    "useless_conversion",
-    "useless_format",
-    "useless_let_if_seq",
-    "useless_transmute",
-    "useless_vec",
-    "vec_box",
-    "vec_init_then_push",
-    "vec_resize_to_zero",
-    "verbose_bit_mask",
-    "verbose_file_reads",
-    "vtable_address_comparisons",
-    "while_immutable_condition",
-    "while_let_loop",
-    "while_let_on_iterator",
-    "wildcard_dependencies",
-    "wildcard_enum_match_arm",
-    "wildcard_imports",
-    "wildcard_in_or_patterns",
-    "write_literal",
-    "write_with_newline",
-    "writeln_empty_string",
-    "wrong_self_convention",
-    "wrong_transmute",
-    "zero_divided_by_zero",
-    "zero_prefixed_literal",
-    "zero_ptr",
-    "zero_sized_map_values",
-    "zst_offset",
-
-}
diff --git a/src/tools/clippy/src/docs/absurd_extreme_comparisons.txt b/src/tools/clippy/src/docs/absurd_extreme_comparisons.txt
deleted file mode 100644
index 590bee28aa2..00000000000
--- a/src/tools/clippy/src/docs/absurd_extreme_comparisons.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Checks for comparisons where one side of the relation is
-either the minimum or maximum value for its type and warns if it involves a
-case that is always true or always false. Only integer and boolean types are
-checked.
-
-### Why is this bad?
-An expression like `min <= x` may misleadingly imply
-that it is possible for `x` to be less than the minimum. Expressions like
-`max < x` are probably mistakes.
-
-### Known problems
-For `usize` the size of the current compile target will
-be assumed (e.g., 64 bits on 64 bit systems). This means code that uses such
-a comparison to detect target pointer width will trigger this lint. One can
-use `mem::sizeof` and compare its value or conditional compilation
-attributes
-like `#[cfg(target_pointer_width = "64")] ..` instead.
-
-### Example
-```
-let vec: Vec<isize> = Vec::new();
-if vec.len() <= 0 {}
-if 100 > i32::MAX {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/alloc_instead_of_core.txt b/src/tools/clippy/src/docs/alloc_instead_of_core.txt
deleted file mode 100644
index 488a36e9276..00000000000
--- a/src/tools/clippy/src/docs/alloc_instead_of_core.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-
-Finds items imported through `alloc` when available through `core`.
-
-### Why is this bad?
-
-Crates which have `no_std` compatibility and may optionally require alloc may wish to ensure types are
-imported from core to ensure disabling `alloc` does not cause the crate to fail to compile. This lint
-is also useful for crates migrating to become `no_std` compatible.
-
-### Example
-```
-use alloc::slice::from_ref;
-```
-Use instead:
-```
-use core::slice::from_ref;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/allow_attributes_without_reason.txt b/src/tools/clippy/src/docs/allow_attributes_without_reason.txt
deleted file mode 100644
index fcc4f49b08b..00000000000
--- a/src/tools/clippy/src/docs/allow_attributes_without_reason.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for attributes that allow lints without a reason.
-
-(This requires the `lint_reasons` feature)
-
-### Why is this bad?
-Allowing a lint should always have a reason. This reason should be documented to
-ensure that others understand the reasoning
-
-### Example
-```
-#![feature(lint_reasons)]
-
-#![allow(clippy::some_lint)]
-```
-
-Use instead:
-```
-#![feature(lint_reasons)]
-
-#![allow(clippy::some_lint, reason = "False positive rust-lang/rust-clippy#1002020")]
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/almost_complete_letter_range.txt b/src/tools/clippy/src/docs/almost_complete_letter_range.txt
deleted file mode 100644
index 01cbaf9eae2..00000000000
--- a/src/tools/clippy/src/docs/almost_complete_letter_range.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for ranges which almost include the entire range of letters from 'a' to 'z', but
-don't because they're a half open range.
-
-### Why is this bad?
-This (`'a'..'z'`) is almost certainly a typo meant to include all letters.
-
-### Example
-```
-let _ = 'a'..'z';
-```
-Use instead:
-```
-let _ = 'a'..='z';
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/almost_swapped.txt b/src/tools/clippy/src/docs/almost_swapped.txt
deleted file mode 100644
index cd10a8d5409..00000000000
--- a/src/tools/clippy/src/docs/almost_swapped.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for `foo = bar; bar = foo` sequences.
-
-### Why is this bad?
-This looks like a failed attempt to swap.
-
-### Example
-```
-a = b;
-b = a;
-```
-If swapping is intended, use `swap()` instead:
-```
-std::mem::swap(&mut a, &mut b);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/approx_constant.txt b/src/tools/clippy/src/docs/approx_constant.txt
deleted file mode 100644
index 393fa4b5ef7..00000000000
--- a/src/tools/clippy/src/docs/approx_constant.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for floating point literals that approximate
-constants which are defined in
-[`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants)
-or
-[`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants),
-respectively, suggesting to use the predefined constant.
-
-### Why is this bad?
-Usually, the definition in the standard library is more
-precise than what people come up with. If you find that your definition is
-actually more precise, please [file a Rust
-issue](https://github.com/rust-lang/rust/issues).
-
-### Example
-```
-let x = 3.14;
-let y = 1_f64 / x;
-```
-Use instead:
-```
-let x = std::f32::consts::PI;
-let y = std::f64::consts::FRAC_1_PI;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/arithmetic_side_effects.txt b/src/tools/clippy/src/docs/arithmetic_side_effects.txt
deleted file mode 100644
index 4ae8bce88ad..00000000000
--- a/src/tools/clippy/src/docs/arithmetic_side_effects.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-### What it does
-Checks any kind of arithmetic operation of any type.
-
-Operators like `+`, `-`, `*` or `<<` are usually capable of overflowing according to the [Rust
-Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow),
-or can panic (`/`, `%`).
-
-Known safe built-in types like `Wrapping` or `Saturating`, floats, operations in constant
-environments, allowed types and non-constant operations that won't overflow are ignored.
-
-### Why is this bad?
-For integers, overflow will trigger a panic in debug builds or wrap the result in
-release mode; division by zero will cause a panic in either mode. As a result, it is
-desirable to explicitly call checked, wrapping or saturating arithmetic methods.
-
-#### Example
-```
-// `n` can be any number, including `i32::MAX`.
-fn foo(n: i32) -> i32 {
-  n + 1
-}
-```
-
-Third-party types can also overflow or present unwanted side-effects.
-
-#### Example
-```
-use rust_decimal::Decimal;
-let _n = Decimal::MAX + Decimal::MAX;
-```
-
-### Allowed types
-Custom allowed types can be specified through the "arithmetic-side-effects-allowed" filter.
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/as_conversions.txt b/src/tools/clippy/src/docs/as_conversions.txt
deleted file mode 100644
index 4af479bd811..00000000000
--- a/src/tools/clippy/src/docs/as_conversions.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-### What it does
-Checks for usage of `as` conversions.
-
-Note that this lint is specialized in linting *every single* use of `as`
-regardless of whether good alternatives exist or not.
-If you want more precise lints for `as`, please consider using these separate lints:
-`unnecessary_cast`, `cast_lossless/cast_possible_truncation/cast_possible_wrap/cast_precision_loss/cast_sign_loss`,
-`fn_to_numeric_cast(_with_truncation)`, `char_lit_as_u8`, `ref_to_mut` and `ptr_as_ptr`.
-There is a good explanation the reason why this lint should work in this way and how it is useful
-[in this issue](https://github.com/rust-lang/rust-clippy/issues/5122).
-
-### Why is this bad?
-`as` conversions will perform many kinds of
-conversions, including silently lossy conversions and dangerous coercions.
-There are cases when it makes sense to use `as`, so the lint is
-Allow by default.
-
-### Example
-```
-let a: u32;
-...
-f(a as u16);
-```
-
-Use instead:
-```
-f(a.try_into()?);
-
-// or
-
-f(a.try_into().expect("Unexpected u16 overflow in f"));
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/as_ptr_cast_mut.txt b/src/tools/clippy/src/docs/as_ptr_cast_mut.txt
deleted file mode 100644
index 228dde996bb..00000000000
--- a/src/tools/clippy/src/docs/as_ptr_cast_mut.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for the result of a `&self`-taking `as_ptr` being cast to a mutable pointer
-
-### Why is this bad?
-Since `as_ptr` takes a `&self`, the pointer won't have write permissions unless interior
-mutability is used, making it unlikely that having it as a mutable pointer is correct.
-
-### Example
-```
-let string = String::with_capacity(1);
-let ptr = string.as_ptr() as *mut u8;
-unsafe { ptr.write(4) }; // UNDEFINED BEHAVIOUR
-```
-Use instead:
-```
-let mut string = String::with_capacity(1);
-let ptr = string.as_mut_ptr();
-unsafe { ptr.write(4) };
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/as_underscore.txt b/src/tools/clippy/src/docs/as_underscore.txt
deleted file mode 100644
index 2d9b0c35893..00000000000
--- a/src/tools/clippy/src/docs/as_underscore.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Check for the usage of `as _` conversion using inferred type.
-
-### Why is this bad?
-The conversion might include lossy conversion and dangerous cast that might go
-undetected due to the type being inferred.
-
-The lint is allowed by default as using `_` is less wordy than always specifying the type.
-
-### Example
-```
-fn foo(n: usize) {}
-let n: u16 = 256;
-foo(n as _);
-```
-Use instead:
-```
-fn foo(n: usize) {}
-let n: u16 = 256;
-foo(n as usize);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/assertions_on_constants.txt b/src/tools/clippy/src/docs/assertions_on_constants.txt
deleted file mode 100644
index 270c1e3b639..00000000000
--- a/src/tools/clippy/src/docs/assertions_on_constants.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Checks for `assert!(true)` and `assert!(false)` calls.
-
-### Why is this bad?
-Will be optimized out by the compiler or should probably be replaced by a
-`panic!()` or `unreachable!()`
-
-### Example
-```
-assert!(false)
-assert!(true)
-const B: bool = false;
-assert!(B)
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/assertions_on_result_states.txt b/src/tools/clippy/src/docs/assertions_on_result_states.txt
deleted file mode 100644
index 0889084fd3a..00000000000
--- a/src/tools/clippy/src/docs/assertions_on_result_states.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Checks for `assert!(r.is_ok())` or `assert!(r.is_err())` calls.
-
-### Why is this bad?
-An assertion failure cannot output an useful message of the error.
-
-### Known problems
-The suggested replacement decreases the readability of code and log output.
-
-### Example
-```
-assert!(r.is_ok());
-assert!(r.is_err());
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/assign_op_pattern.txt b/src/tools/clippy/src/docs/assign_op_pattern.txt
deleted file mode 100644
index f355c0cc18d..00000000000
--- a/src/tools/clippy/src/docs/assign_op_pattern.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-### What it does
-Checks for `a = a op b` or `a = b commutative_op a`
-patterns.
-
-### Why is this bad?
-These can be written as the shorter `a op= b`.
-
-### Known problems
-While forbidden by the spec, `OpAssign` traits may have
-implementations that differ from the regular `Op` impl.
-
-### Example
-```
-let mut a = 5;
-let b = 0;
-// ...
-
-a = a + b;
-```
-
-Use instead:
-```
-let mut a = 5;
-let b = 0;
-// ...
-
-a += b;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/async_yields_async.txt b/src/tools/clippy/src/docs/async_yields_async.txt
deleted file mode 100644
index a40de6d2e47..00000000000
--- a/src/tools/clippy/src/docs/async_yields_async.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-### What it does
-Checks for async blocks that yield values of types
-that can themselves be awaited.
-
-### Why is this bad?
-An await is likely missing.
-
-### Example
-```
-async fn foo() {}
-
-fn bar() {
-  let x = async {
-    foo()
-  };
-}
-```
-
-Use instead:
-```
-async fn foo() {}
-
-fn bar() {
-  let x = async {
-    foo().await
-  };
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/await_holding_invalid_type.txt b/src/tools/clippy/src/docs/await_holding_invalid_type.txt
deleted file mode 100644
index e9c768772ff..00000000000
--- a/src/tools/clippy/src/docs/await_holding_invalid_type.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Allows users to configure types which should not be held across `await`
-suspension points.
-
-### Why is this bad?
-There are some types which are perfectly "safe" to be used concurrently
-from a memory access perspective but will cause bugs at runtime if they
-are held in such a way.
-
-### Example
-
-```
-await-holding-invalid-types = [
-  # You can specify a type name
-  "CustomLockType",
-  # You can (optionally) specify a reason
-  { path = "OtherCustomLockType", reason = "Relies on a thread local" }
-]
-```
-
-```
-struct CustomLockType;
-struct OtherCustomLockType;
-async fn foo() {
-  let _x = CustomLockType;
-  let _y = OtherCustomLockType;
-  baz().await; // Lint violation
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/await_holding_lock.txt b/src/tools/clippy/src/docs/await_holding_lock.txt
deleted file mode 100644
index 0f450a11160..00000000000
--- a/src/tools/clippy/src/docs/await_holding_lock.txt
+++ /dev/null
@@ -1,51 +0,0 @@
-### What it does
-Checks for calls to await while holding a non-async-aware MutexGuard.
-
-### Why is this bad?
-The Mutex types found in std::sync and parking_lot
-are not designed to operate in an async context across await points.
-
-There are two potential solutions. One is to use an async-aware Mutex
-type. Many asynchronous foundation crates provide such a Mutex type. The
-other solution is to ensure the mutex is unlocked before calling await,
-either by introducing a scope or an explicit call to Drop::drop.
-
-### Known problems
-Will report false positive for explicitly dropped guards
-([#6446](https://github.com/rust-lang/rust-clippy/issues/6446)). A workaround for this is
-to wrap the `.lock()` call in a block instead of explicitly dropping the guard.
-
-### Example
-```
-async fn foo(x: &Mutex<u32>) {
-  let mut guard = x.lock().unwrap();
-  *guard += 1;
-  baz().await;
-}
-
-async fn bar(x: &Mutex<u32>) {
-  let mut guard = x.lock().unwrap();
-  *guard += 1;
-  drop(guard); // explicit drop
-  baz().await;
-}
-```
-
-Use instead:
-```
-async fn foo(x: &Mutex<u32>) {
-  {
-    let mut guard = x.lock().unwrap();
-    *guard += 1;
-  }
-  baz().await;
-}
-
-async fn bar(x: &Mutex<u32>) {
-  {
-    let mut guard = x.lock().unwrap();
-    *guard += 1;
-  } // guard dropped here at end of scope
-  baz().await;
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/await_holding_refcell_ref.txt b/src/tools/clippy/src/docs/await_holding_refcell_ref.txt
deleted file mode 100644
index 226a261b9cc..00000000000
--- a/src/tools/clippy/src/docs/await_holding_refcell_ref.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-### What it does
-Checks for calls to await while holding a `RefCell` `Ref` or `RefMut`.
-
-### Why is this bad?
-`RefCell` refs only check for exclusive mutable access
-at runtime. Holding onto a `RefCell` ref across an `await` suspension point
-risks panics from a mutable ref shared while other refs are outstanding.
-
-### Known problems
-Will report false positive for explicitly dropped refs
-([#6353](https://github.com/rust-lang/rust-clippy/issues/6353)). A workaround for this is
-to wrap the `.borrow[_mut]()` call in a block instead of explicitly dropping the ref.
-
-### Example
-```
-async fn foo(x: &RefCell<u32>) {
-  let mut y = x.borrow_mut();
-  *y += 1;
-  baz().await;
-}
-
-async fn bar(x: &RefCell<u32>) {
-  let mut y = x.borrow_mut();
-  *y += 1;
-  drop(y); // explicit drop
-  baz().await;
-}
-```
-
-Use instead:
-```
-async fn foo(x: &RefCell<u32>) {
-  {
-     let mut y = x.borrow_mut();
-     *y += 1;
-  }
-  baz().await;
-}
-
-async fn bar(x: &RefCell<u32>) {
-  {
-    let mut y = x.borrow_mut();
-    *y += 1;
-  } // y dropped here at end of scope
-  baz().await;
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/bad_bit_mask.txt b/src/tools/clippy/src/docs/bad_bit_mask.txt
deleted file mode 100644
index d40024ee562..00000000000
--- a/src/tools/clippy/src/docs/bad_bit_mask.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-### What it does
-Checks for incompatible bit masks in comparisons.
-
-The formula for detecting if an expression of the type `_ <bit_op> m
-<cmp_op> c` (where `<bit_op>` is one of {`&`, `|`} and `<cmp_op>` is one of
-{`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following
-table:
-
-|Comparison  |Bit Op|Example      |is always|Formula               |
-|------------|------|-------------|---------|----------------------|
-|`==` or `!=`| `&`  |`x & 2 == 3` |`false`  |`c & m != c`          |
-|`<`  or `>=`| `&`  |`x & 2 < 3`  |`true`   |`m < c`               |
-|`>`  or `<=`| `&`  |`x & 1 > 1`  |`false`  |`m <= c`              |
-|`==` or `!=`| `\|` |`x \| 1 == 0`|`false`  |`c \| m != c`         |
-|`<`  or `>=`| `\|` |`x \| 1 < 1` |`false`  |`m >= c`              |
-|`<=` or `>` | `\|` |`x \| 1 > 0` |`true`   |`m > c`               |
-
-### Why is this bad?
-If the bits that the comparison cares about are always
-set to zero or one by the bit mask, the comparison is constant `true` or
-`false` (depending on mask, compared value, and operators).
-
-So the code is actively misleading, and the only reason someone would write
-this intentionally is to win an underhanded Rust contest or create a
-test-case for this lint.
-
-### Example
-```
-if (x & 1 == 2) { }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/bind_instead_of_map.txt b/src/tools/clippy/src/docs/bind_instead_of_map.txt
deleted file mode 100644
index 148575803d3..00000000000
--- a/src/tools/clippy/src/docs/bind_instead_of_map.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for usage of `_.and_then(|x| Some(y))`, `_.and_then(|x| Ok(y))` or
-`_.or_else(|x| Err(y))`.
-
-### Why is this bad?
-Readability, this can be written more concisely as
-`_.map(|x| y)` or `_.map_err(|x| y)`.
-
-### Example
-```
-let _ = opt().and_then(|s| Some(s.len()));
-let _ = res().and_then(|s| if s.len() == 42 { Ok(10) } else { Ok(20) });
-let _ = res().or_else(|s| if s.len() == 42 { Err(10) } else { Err(20) });
-```
-
-The correct use would be:
-
-```
-let _ = opt().map(|s| s.len());
-let _ = res().map(|s| if s.len() == 42 { 10 } else { 20 });
-let _ = res().map_err(|s| if s.len() == 42 { 10 } else { 20 });
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/blanket_clippy_restriction_lints.txt b/src/tools/clippy/src/docs/blanket_clippy_restriction_lints.txt
deleted file mode 100644
index 28a4ebf7169..00000000000
--- a/src/tools/clippy/src/docs/blanket_clippy_restriction_lints.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category.
-
-### Why is this bad?
-Restriction lints sometimes are in contrast with other lints or even go against idiomatic rust.
-These lints should only be enabled on a lint-by-lint basis and with careful consideration.
-
-### Example
-```
-#![deny(clippy::restriction)]
-```
-
-Use instead:
-```
-#![deny(clippy::as_conversions)]
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/blocks_in_if_conditions.txt b/src/tools/clippy/src/docs/blocks_in_if_conditions.txt
deleted file mode 100644
index 3afa14853fd..00000000000
--- a/src/tools/clippy/src/docs/blocks_in_if_conditions.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for `if` conditions that use blocks containing an
-expression, statements or conditions that use closures with blocks.
-
-### Why is this bad?
-Style, using blocks in the condition makes it hard to read.
-
-### Examples
-```
-if { true } { /* ... */ }
-
-if { let x = somefunc(); x } { /* ... */ }
-```
-
-Use instead:
-```
-if true { /* ... */ }
-
-let res = { let x = somefunc(); x };
-if res { /* ... */ }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/bool_assert_comparison.txt b/src/tools/clippy/src/docs/bool_assert_comparison.txt
deleted file mode 100644
index df7ca00cc2b..00000000000
--- a/src/tools/clippy/src/docs/bool_assert_comparison.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-This lint warns about boolean comparisons in assert-like macros.
-
-### Why is this bad?
-It is shorter to use the equivalent.
-
-### Example
-```
-assert_eq!("a".is_empty(), false);
-assert_ne!("a".is_empty(), true);
-```
-
-Use instead:
-```
-assert!(!"a".is_empty());
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/bool_comparison.txt b/src/tools/clippy/src/docs/bool_comparison.txt
deleted file mode 100644
index 0996f60cec4..00000000000
--- a/src/tools/clippy/src/docs/bool_comparison.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for expressions of the form `x == true`,
-`x != true` and order comparisons such as `x < true` (or vice versa) and
-suggest using the variable directly.
-
-### Why is this bad?
-Unnecessary code.
-
-### Example
-```
-if x == true {}
-if y == false {}
-```
-use `x` directly:
-```
-if x {}
-if !y {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/bool_to_int_with_if.txt b/src/tools/clippy/src/docs/bool_to_int_with_if.txt
deleted file mode 100644
index 63535b454c9..00000000000
--- a/src/tools/clippy/src/docs/bool_to_int_with_if.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Instead of using an if statement to convert a bool to an int,
-this lint suggests using a `from()` function or an `as` coercion.
-
-### Why is this bad?
-Coercion or `from()` is idiomatic way to convert bool to a number.
-Both methods are guaranteed to return 1 for true, and 0 for false.
-
-See https://doc.rust-lang.org/std/primitive.bool.html#impl-From%3Cbool%3E
-
-### Example
-```
-if condition {
-    1_i64
-} else {
-    0
-};
-```
-Use instead:
-```
-i64::from(condition);
-```
-or
-```
-condition as i64;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/borrow_as_ptr.txt b/src/tools/clippy/src/docs/borrow_as_ptr.txt
deleted file mode 100644
index 0be865abd57..00000000000
--- a/src/tools/clippy/src/docs/borrow_as_ptr.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for the usage of `&expr as *const T` or
-`&mut expr as *mut T`, and suggest using `ptr::addr_of` or
-`ptr::addr_of_mut` instead.
-
-### Why is this bad?
-This would improve readability and avoid creating a reference
-that points to an uninitialized value or unaligned place.
-Read the `ptr::addr_of` docs for more information.
-
-### Example
-```
-let val = 1;
-let p = &val as *const i32;
-
-let mut val_mut = 1;
-let p_mut = &mut val_mut as *mut i32;
-```
-Use instead:
-```
-let val = 1;
-let p = std::ptr::addr_of!(val);
-
-let mut val_mut = 1;
-let p_mut = std::ptr::addr_of_mut!(val_mut);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/borrow_deref_ref.txt b/src/tools/clippy/src/docs/borrow_deref_ref.txt
deleted file mode 100644
index 352480d3f26..00000000000
--- a/src/tools/clippy/src/docs/borrow_deref_ref.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for `&*(&T)`.
-
-### Why is this bad?
-Dereferencing and then borrowing a reference value has no effect in most cases.
-
-### Known problems
-False negative on such code:
-```
-let x = &12;
-let addr_x = &x as *const _ as usize;
-let addr_y = &&*x as *const _ as usize; // assert ok now, and lint triggered.
-                                        // But if we fix it, assert will fail.
-assert_ne!(addr_x, addr_y);
-```
-
-### Example
-```
-let s = &String::new();
-
-let a: &String = &* s;
-```
-
-Use instead:
-```
-let a: &String = s;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/borrow_interior_mutable_const.txt b/src/tools/clippy/src/docs/borrow_interior_mutable_const.txt
deleted file mode 100644
index e55b6a77e66..00000000000
--- a/src/tools/clippy/src/docs/borrow_interior_mutable_const.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-### What it does
-Checks if `const` items which is interior mutable (e.g.,
-contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.) has been borrowed directly.
-
-### Why is this bad?
-Consts are copied everywhere they are referenced, i.e.,
-every time you refer to the const a fresh instance of the `Cell` or `Mutex`
-or `AtomicXxxx` will be created, which defeats the whole purpose of using
-these types in the first place.
-
-The `const` value should be stored inside a `static` item.
-
-### Known problems
-When an enum has variants with interior mutability, use of its non
-interior mutable variants can generate false positives. See issue
-[#3962](https://github.com/rust-lang/rust-clippy/issues/3962)
-
-Types that have underlying or potential interior mutability trigger the lint whether
-the interior mutable field is used or not. See issues
-[#5812](https://github.com/rust-lang/rust-clippy/issues/5812) and
-[#3825](https://github.com/rust-lang/rust-clippy/issues/3825)
-
-### Example
-```
-use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
-const CONST_ATOM: AtomicUsize = AtomicUsize::new(12);
-
-CONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged
-assert_eq!(CONST_ATOM.load(SeqCst), 12); // because the CONST_ATOM in these lines are distinct
-```
-
-Use instead:
-```
-use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
-const CONST_ATOM: AtomicUsize = AtomicUsize::new(12);
-
-static STATIC_ATOM: AtomicUsize = CONST_ATOM;
-STATIC_ATOM.store(9, SeqCst);
-assert_eq!(STATIC_ATOM.load(SeqCst), 9); // use a `static` item to refer to the same instance
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/borrowed_box.txt b/src/tools/clippy/src/docs/borrowed_box.txt
deleted file mode 100644
index d7089be662a..00000000000
--- a/src/tools/clippy/src/docs/borrowed_box.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for use of `&Box<T>` anywhere in the code.
-Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information.
-
-### Why is this bad?
-A `&Box<T>` parameter requires the function caller to box `T` first before passing it to a function.
-Using `&T` defines a concrete type for the parameter and generalizes the function, this would also
-auto-deref to `&T` at the function call site if passed a `&Box<T>`.
-
-### Example
-```
-fn foo(bar: &Box<T>) { ... }
-```
-
-Better:
-
-```
-fn foo(bar: &T) { ... }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/box_collection.txt b/src/tools/clippy/src/docs/box_collection.txt
deleted file mode 100644
index 053f24c4628..00000000000
--- a/src/tools/clippy/src/docs/box_collection.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for use of `Box<T>` where T is a collection such as Vec anywhere in the code.
-Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information.
-
-### Why is this bad?
-Collections already keeps their contents in a separate area on
-the heap. So if you `Box` them, you just add another level of indirection
-without any benefit whatsoever.
-
-### Example
-```
-struct X {
-    values: Box<Vec<Foo>>,
-}
-```
-
-Better:
-
-```
-struct X {
-    values: Vec<Foo>,
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/box_default.txt b/src/tools/clippy/src/docs/box_default.txt
deleted file mode 100644
index 1c670c77333..00000000000
--- a/src/tools/clippy/src/docs/box_default.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-checks for `Box::new(T::default())`, which is better written as
-`Box::<T>::default()`.
-
-### Why is this bad?
-First, it's more complex, involving two calls instead of one.
-Second, `Box::default()` can be faster
-[in certain cases](https://nnethercote.github.io/perf-book/standard-library-types.html#box).
-
-### Example
-```
-let x: Box<String> = Box::new(Default::default());
-```
-Use instead:
-```
-let x: Box<String> = Box::default();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/boxed_local.txt b/src/tools/clippy/src/docs/boxed_local.txt
deleted file mode 100644
index 8b1febf1455..00000000000
--- a/src/tools/clippy/src/docs/boxed_local.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for usage of `Box<T>` where an unboxed `T` would
-work fine.
-
-### Why is this bad?
-This is an unnecessary allocation, and bad for
-performance. It is only necessary to allocate if you wish to move the box
-into something.
-
-### Example
-```
-fn foo(x: Box<u32>) {}
-```
-
-Use instead:
-```
-fn foo(x: u32) {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/branches_sharing_code.txt b/src/tools/clippy/src/docs/branches_sharing_code.txt
deleted file mode 100644
index 79be6124798..00000000000
--- a/src/tools/clippy/src/docs/branches_sharing_code.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-### What it does
-Checks if the `if` and `else` block contain shared code that can be
-moved out of the blocks.
-
-### Why is this bad?
-Duplicate code is less maintainable.
-
-### Known problems
-* The lint doesn't check if the moved expressions modify values that are being used in
-  the if condition. The suggestion can in that case modify the behavior of the program.
-  See [rust-clippy#7452](https://github.com/rust-lang/rust-clippy/issues/7452)
-
-### Example
-```
-let foo = if … {
-    println!("Hello World");
-    13
-} else {
-    println!("Hello World");
-    42
-};
-```
-
-Use instead:
-```
-println!("Hello World");
-let foo = if … {
-    13
-} else {
-    42
-};
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/builtin_type_shadow.txt b/src/tools/clippy/src/docs/builtin_type_shadow.txt
deleted file mode 100644
index 15b1c9df7ba..00000000000
--- a/src/tools/clippy/src/docs/builtin_type_shadow.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Warns if a generic shadows a built-in type.
-
-### Why is this bad?
-This gives surprising type errors.
-
-### Example
-
-```
-impl<u32> Foo<u32> {
-    fn impl_func(&self) -> u32 {
-        42
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/bytes_count_to_len.txt b/src/tools/clippy/src/docs/bytes_count_to_len.txt
deleted file mode 100644
index ca7bf9a38da..00000000000
--- a/src/tools/clippy/src/docs/bytes_count_to_len.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-It checks for `str::bytes().count()` and suggests replacing it with
-`str::len()`.
-
-### Why is this bad?
-`str::bytes().count()` is longer and may not be as performant as using
-`str::len()`.
-
-### Example
-```
-"hello".bytes().count();
-String::from("hello").bytes().count();
-```
-Use instead:
-```
-"hello".len();
-String::from("hello").len();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/bytes_nth.txt b/src/tools/clippy/src/docs/bytes_nth.txt
deleted file mode 100644
index 260de343353..00000000000
--- a/src/tools/clippy/src/docs/bytes_nth.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for the use of `.bytes().nth()`.
-
-### Why is this bad?
-`.as_bytes().get()` is more efficient and more
-readable.
-
-### Example
-```
-"Hello".bytes().nth(3);
-```
-
-Use instead:
-```
-"Hello".as_bytes().get(3);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cargo_common_metadata.txt b/src/tools/clippy/src/docs/cargo_common_metadata.txt
deleted file mode 100644
index 1998647a927..00000000000
--- a/src/tools/clippy/src/docs/cargo_common_metadata.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-### What it does
-Checks to see if all common metadata is defined in
-`Cargo.toml`. See: https://rust-lang-nursery.github.io/api-guidelines/documentation.html#cargotoml-includes-all-common-metadata-c-metadata
-
-### Why is this bad?
-It will be more difficult for users to discover the
-purpose of the crate, and key information related to it.
-
-### Example
-```
-[package]
-name = "clippy"
-version = "0.0.212"
-repository = "https://github.com/rust-lang/rust-clippy"
-readme = "README.md"
-license = "MIT OR Apache-2.0"
-keywords = ["clippy", "lint", "plugin"]
-categories = ["development-tools", "development-tools::cargo-plugins"]
-```
-
-Should include a description field like:
-
-```
-[package]
-name = "clippy"
-version = "0.0.212"
-description = "A bunch of helpful lints to avoid common pitfalls in Rust"
-repository = "https://github.com/rust-lang/rust-clippy"
-readme = "README.md"
-license = "MIT OR Apache-2.0"
-keywords = ["clippy", "lint", "plugin"]
-categories = ["development-tools", "development-tools::cargo-plugins"]
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/case_sensitive_file_extension_comparisons.txt b/src/tools/clippy/src/docs/case_sensitive_file_extension_comparisons.txt
deleted file mode 100644
index 8e6e18ed4e2..00000000000
--- a/src/tools/clippy/src/docs/case_sensitive_file_extension_comparisons.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for calls to `ends_with` with possible file extensions
-and suggests to use a case-insensitive approach instead.
-
-### Why is this bad?
-`ends_with` is case-sensitive and may not detect files with a valid extension.
-
-### Example
-```
-fn is_rust_file(filename: &str) -> bool {
-    filename.ends_with(".rs")
-}
-```
-Use instead:
-```
-fn is_rust_file(filename: &str) -> bool {
-    let filename = std::path::Path::new(filename);
-    filename.extension()
-        .map_or(false, |ext| ext.eq_ignore_ascii_case("rs"))
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cast_abs_to_unsigned.txt b/src/tools/clippy/src/docs/cast_abs_to_unsigned.txt
deleted file mode 100644
index c5d8ee034ce..00000000000
--- a/src/tools/clippy/src/docs/cast_abs_to_unsigned.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for uses of the `abs()` method that cast the result to unsigned.
-
-### Why is this bad?
-The `unsigned_abs()` method avoids panic when called on the MIN value.
-
-### Example
-```
-let x: i32 = -42;
-let y: u32 = x.abs() as u32;
-```
-Use instead:
-```
-let x: i32 = -42;
-let y: u32 = x.unsigned_abs();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cast_enum_constructor.txt b/src/tools/clippy/src/docs/cast_enum_constructor.txt
deleted file mode 100644
index 675c03a42bc..00000000000
--- a/src/tools/clippy/src/docs/cast_enum_constructor.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-### What it does
-Checks for casts from an enum tuple constructor to an integer.
-
-### Why is this bad?
-The cast is easily confused with casting a c-like enum value to an integer.
-
-### Example
-```
-enum E { X(i32) };
-let _ = E::X as usize;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cast_enum_truncation.txt b/src/tools/clippy/src/docs/cast_enum_truncation.txt
deleted file mode 100644
index abe32a8296d..00000000000
--- a/src/tools/clippy/src/docs/cast_enum_truncation.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for casts from an enum type to an integral type which will definitely truncate the
-value.
-
-### Why is this bad?
-The resulting integral value will not match the value of the variant it came from.
-
-### Example
-```
-enum E { X = 256 };
-let _ = E::X as u8;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cast_lossless.txt b/src/tools/clippy/src/docs/cast_lossless.txt
deleted file mode 100644
index c3a61dd470f..00000000000
--- a/src/tools/clippy/src/docs/cast_lossless.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for casts between numerical types that may
-be replaced by safe conversion functions.
-
-### Why is this bad?
-Rust's `as` keyword will perform many kinds of
-conversions, including silently lossy conversions. Conversion functions such
-as `i32::from` will only perform lossless conversions. Using the conversion
-functions prevents conversions from turning into silent lossy conversions if
-the types of the input expressions ever change, and make it easier for
-people reading the code to know that the conversion is lossless.
-
-### Example
-```
-fn as_u64(x: u8) -> u64 {
-    x as u64
-}
-```
-
-Using `::from` would look like this:
-
-```
-fn as_u64(x: u8) -> u64 {
-    u64::from(x)
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cast_nan_to_int.txt b/src/tools/clippy/src/docs/cast_nan_to_int.txt
deleted file mode 100644
index 122f5da0c92..00000000000
--- a/src/tools/clippy/src/docs/cast_nan_to_int.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for a known NaN float being cast to an integer
-
-### Why is this bad?
-NaNs are cast into zero, so one could simply use this and make the
-code more readable. The lint could also hint at a programmer error.
-
-### Example
-```
-let _: (0.0_f32 / 0.0) as u64;
-```
-Use instead:
-```
-let _: = 0_u64;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cast_possible_truncation.txt b/src/tools/clippy/src/docs/cast_possible_truncation.txt
deleted file mode 100644
index 0b164848cc7..00000000000
--- a/src/tools/clippy/src/docs/cast_possible_truncation.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for casts between numerical types that may
-truncate large values. This is expected behavior, so the cast is `Allow` by
-default.
-
-### Why is this bad?
-In some problem domains, it is good practice to avoid
-truncation. This lint can be activated to help assess where additional
-checks could be beneficial.
-
-### Example
-```
-fn as_u8(x: u64) -> u8 {
-    x as u8
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cast_possible_wrap.txt b/src/tools/clippy/src/docs/cast_possible_wrap.txt
deleted file mode 100644
index f883fc9cfb9..00000000000
--- a/src/tools/clippy/src/docs/cast_possible_wrap.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for casts from an unsigned type to a signed type of
-the same size. Performing such a cast is a 'no-op' for the compiler,
-i.e., nothing is changed at the bit level, and the binary representation of
-the value is reinterpreted. This can cause wrapping if the value is too big
-for the target signed type. However, the cast works as defined, so this lint
-is `Allow` by default.
-
-### Why is this bad?
-While such a cast is not bad in itself, the results can
-be surprising when this is not the intended behavior, as demonstrated by the
-example below.
-
-### Example
-```
-u32::MAX as i32; // will yield a value of `-1`
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cast_precision_loss.txt b/src/tools/clippy/src/docs/cast_precision_loss.txt
deleted file mode 100644
index f915d9f8a6d..00000000000
--- a/src/tools/clippy/src/docs/cast_precision_loss.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for casts from any numerical to a float type where
-the receiving type cannot store all values from the original type without
-rounding errors. This possible rounding is to be expected, so this lint is
-`Allow` by default.
-
-Basically, this warns on casting any integer with 32 or more bits to `f32`
-or any 64-bit integer to `f64`.
-
-### Why is this bad?
-It's not bad at all. But in some applications it can be
-helpful to know where precision loss can take place. This lint can help find
-those places in the code.
-
-### Example
-```
-let x = u64::MAX;
-x as f64;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cast_ptr_alignment.txt b/src/tools/clippy/src/docs/cast_ptr_alignment.txt
deleted file mode 100644
index 6a6d4dcaa2a..00000000000
--- a/src/tools/clippy/src/docs/cast_ptr_alignment.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for casts, using `as` or `pointer::cast`,
-from a less-strictly-aligned pointer to a more-strictly-aligned pointer
-
-### Why is this bad?
-Dereferencing the resulting pointer may be undefined
-behavior.
-
-### Known problems
-Using `std::ptr::read_unaligned` and `std::ptr::write_unaligned` or similar
-on the resulting pointer is fine. Is over-zealous: Casts with manual alignment checks or casts like
-u64-> u8 -> u16 can be fine. Miri is able to do a more in-depth analysis.
-
-### Example
-```
-let _ = (&1u8 as *const u8) as *const u16;
-let _ = (&mut 1u8 as *mut u8) as *mut u16;
-
-(&1u8 as *const u8).cast::<u16>();
-(&mut 1u8 as *mut u8).cast::<u16>();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cast_ref_to_mut.txt b/src/tools/clippy/src/docs/cast_ref_to_mut.txt
deleted file mode 100644
index fb5b4dbb62d..00000000000
--- a/src/tools/clippy/src/docs/cast_ref_to_mut.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-### What it does
-Checks for casts of `&T` to `&mut T` anywhere in the code.
-
-### Why is this bad?
-It’s basically guaranteed to be undefined behavior.
-`UnsafeCell` is the only way to obtain aliasable data that is considered
-mutable.
-
-### Example
-```
-fn x(r: &i32) {
-    unsafe {
-        *(r as *const _ as *mut _) += 1;
-    }
-}
-```
-
-Instead consider using interior mutability types.
-
-```
-use std::cell::UnsafeCell;
-
-fn x(r: &UnsafeCell<i32>) {
-    unsafe {
-        *r.get() += 1;
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cast_sign_loss.txt b/src/tools/clippy/src/docs/cast_sign_loss.txt
deleted file mode 100644
index d64fe1b07f4..00000000000
--- a/src/tools/clippy/src/docs/cast_sign_loss.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for casts from a signed to an unsigned numerical
-type. In this case, negative values wrap around to large positive values,
-which can be quite surprising in practice. However, as the cast works as
-defined, this lint is `Allow` by default.
-
-### Why is this bad?
-Possibly surprising results. You can activate this lint
-as a one-time check to see where numerical wrapping can arise.
-
-### Example
-```
-let y: i8 = -1;
-y as u128; // will return 18446744073709551615
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cast_slice_different_sizes.txt b/src/tools/clippy/src/docs/cast_slice_different_sizes.txt
deleted file mode 100644
index c01ef0ba92c..00000000000
--- a/src/tools/clippy/src/docs/cast_slice_different_sizes.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-### What it does
-Checks for `as` casts between raw pointers to slices with differently sized elements.
-
-### Why is this bad?
-The produced raw pointer to a slice does not update its length metadata. The produced
-pointer will point to a different number of bytes than the original pointer because the
-length metadata of a raw slice pointer is in elements rather than bytes.
-Producing a slice reference from the raw pointer will either create a slice with
-less data (which can be surprising) or create a slice with more data and cause Undefined Behavior.
-
-### Example
-// Missing data
-```
-let a = [1_i32, 2, 3, 4];
-let p = &a as *const [i32] as *const [u8];
-unsafe {
-    println!("{:?}", &*p);
-}
-```
-// Undefined Behavior (note: also potential alignment issues)
-```
-let a = [1_u8, 2, 3, 4];
-let p = &a as *const [u8] as *const [u32];
-unsafe {
-    println!("{:?}", &*p);
-}
-```
-Instead use `ptr::slice_from_raw_parts` to construct a slice from a data pointer and the correct length
-```
-let a = [1_i32, 2, 3, 4];
-let old_ptr = &a as *const [i32];
-// The data pointer is cast to a pointer to the target `u8` not `[u8]`
-// The length comes from the known length of 4 i32s times the 4 bytes per i32
-let new_ptr = core::ptr::slice_from_raw_parts(old_ptr as *const u8, 16);
-unsafe {
-    println!("{:?}", &*new_ptr);
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cast_slice_from_raw_parts.txt b/src/tools/clippy/src/docs/cast_slice_from_raw_parts.txt
deleted file mode 100644
index b58c739766a..00000000000
--- a/src/tools/clippy/src/docs/cast_slice_from_raw_parts.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for a raw slice being cast to a slice pointer
-
-### Why is this bad?
-This can result in multiple `&mut` references to the same location when only a pointer is
-required.
-`ptr::slice_from_raw_parts` is a safe alternative that doesn't require
-the same [safety requirements] to be upheld.
-
-### Example
-```
-let _: *const [u8] = std::slice::from_raw_parts(ptr, len) as *const _;
-let _: *mut [u8] = std::slice::from_raw_parts_mut(ptr, len) as *mut _;
-```
-Use instead:
-```
-let _: *const [u8] = std::ptr::slice_from_raw_parts(ptr, len);
-let _: *mut [u8] = std::ptr::slice_from_raw_parts_mut(ptr, len);
-```
-[safety requirements]: https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html#safety
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/char_lit_as_u8.txt b/src/tools/clippy/src/docs/char_lit_as_u8.txt
deleted file mode 100644
index 00d60b9a451..00000000000
--- a/src/tools/clippy/src/docs/char_lit_as_u8.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for expressions where a character literal is cast
-to `u8` and suggests using a byte literal instead.
-
-### Why is this bad?
-In general, casting values to smaller types is
-error-prone and should be avoided where possible. In the particular case of
-converting a character literal to u8, it is easy to avoid by just using a
-byte literal instead. As an added bonus, `b'a'` is even slightly shorter
-than `'a' as u8`.
-
-### Example
-```
-'x' as u8
-```
-
-A better version, using the byte literal:
-
-```
-b'x'
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/chars_last_cmp.txt b/src/tools/clippy/src/docs/chars_last_cmp.txt
deleted file mode 100644
index 4c1d8838973..00000000000
--- a/src/tools/clippy/src/docs/chars_last_cmp.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for usage of `_.chars().last()` or
-`_.chars().next_back()` on a `str` to check if it ends with a given char.
-
-### Why is this bad?
-Readability, this can be written more concisely as
-`_.ends_with(_)`.
-
-### Example
-```
-name.chars().last() == Some('_') || name.chars().next_back() == Some('-');
-```
-
-Use instead:
-```
-name.ends_with('_') || name.ends_with('-');
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/chars_next_cmp.txt b/src/tools/clippy/src/docs/chars_next_cmp.txt
deleted file mode 100644
index 77cbce2de00..00000000000
--- a/src/tools/clippy/src/docs/chars_next_cmp.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for usage of `.chars().next()` on a `str` to check
-if it starts with a given char.
-
-### Why is this bad?
-Readability, this can be written more concisely as
-`_.starts_with(_)`.
-
-### Example
-```
-let name = "foo";
-if name.chars().next() == Some('_') {};
-```
-
-Use instead:
-```
-let name = "foo";
-if name.starts_with('_') {};
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/checked_conversions.txt b/src/tools/clippy/src/docs/checked_conversions.txt
deleted file mode 100644
index 536b01294ee..00000000000
--- a/src/tools/clippy/src/docs/checked_conversions.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for explicit bounds checking when casting.
-
-### Why is this bad?
-Reduces the readability of statements & is error prone.
-
-### Example
-```
-foo <= i32::MAX as u32;
-```
-
-Use instead:
-```
-i32::try_from(foo).is_ok();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/clone_double_ref.txt b/src/tools/clippy/src/docs/clone_double_ref.txt
deleted file mode 100644
index 2729635bd24..00000000000
--- a/src/tools/clippy/src/docs/clone_double_ref.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for usage of `.clone()` on an `&&T`.
-
-### Why is this bad?
-Cloning an `&&T` copies the inner `&T`, instead of
-cloning the underlying `T`.
-
-### Example
-```
-fn main() {
-    let x = vec![1];
-    let y = &&x;
-    let z = y.clone();
-    println!("{:p} {:p}", *y, z); // prints out the same pointer
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/clone_on_copy.txt b/src/tools/clippy/src/docs/clone_on_copy.txt
deleted file mode 100644
index 99a0bdb4c4a..00000000000
--- a/src/tools/clippy/src/docs/clone_on_copy.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-### What it does
-Checks for usage of `.clone()` on a `Copy` type.
-
-### Why is this bad?
-The only reason `Copy` types implement `Clone` is for
-generics, not for using the `clone` method on a concrete type.
-
-### Example
-```
-42u64.clone();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/clone_on_ref_ptr.txt b/src/tools/clippy/src/docs/clone_on_ref_ptr.txt
deleted file mode 100644
index 2d83f8fefc1..00000000000
--- a/src/tools/clippy/src/docs/clone_on_ref_ptr.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for usage of `.clone()` on a ref-counted pointer,
-(`Rc`, `Arc`, `rc::Weak`, or `sync::Weak`), and suggests calling Clone via unified
-function syntax instead (e.g., `Rc::clone(foo)`).
-
-### Why is this bad?
-Calling '.clone()' on an Rc, Arc, or Weak
-can obscure the fact that only the pointer is being cloned, not the underlying
-data.
-
-### Example
-```
-let x = Rc::new(1);
-
-x.clone();
-```
-
-Use instead:
-```
-Rc::clone(&x);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cloned_instead_of_copied.txt b/src/tools/clippy/src/docs/cloned_instead_of_copied.txt
deleted file mode 100644
index 2f2014d5fd2..00000000000
--- a/src/tools/clippy/src/docs/cloned_instead_of_copied.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for usages of `cloned()` on an `Iterator` or `Option` where
-`copied()` could be used instead.
-
-### Why is this bad?
-`copied()` is better because it guarantees that the type being cloned
-implements `Copy`.
-
-### Example
-```
-[1, 2, 3].iter().cloned();
-```
-Use instead:
-```
-[1, 2, 3].iter().copied();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cmp_nan.txt b/src/tools/clippy/src/docs/cmp_nan.txt
deleted file mode 100644
index e2ad04d9323..00000000000
--- a/src/tools/clippy/src/docs/cmp_nan.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for comparisons to NaN.
-
-### Why is this bad?
-NaN does not compare meaningfully to anything – not
-even itself – so those comparisons are simply wrong.
-
-### Example
-```
-if x == f32::NAN { }
-```
-
-Use instead:
-```
-if x.is_nan() { }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cmp_null.txt b/src/tools/clippy/src/docs/cmp_null.txt
deleted file mode 100644
index 02fd15124f0..00000000000
--- a/src/tools/clippy/src/docs/cmp_null.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-This lint checks for equality comparisons with `ptr::null`
-
-### Why is this bad?
-It's easier and more readable to use the inherent
-`.is_null()`
-method instead
-
-### Example
-```
-use std::ptr;
-
-if x == ptr::null {
-    // ..
-}
-```
-
-Use instead:
-```
-if x.is_null() {
-    // ..
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cmp_owned.txt b/src/tools/clippy/src/docs/cmp_owned.txt
deleted file mode 100644
index f8d4956ff1d..00000000000
--- a/src/tools/clippy/src/docs/cmp_owned.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for conversions to owned values just for the sake
-of a comparison.
-
-### Why is this bad?
-The comparison can operate on a reference, so creating
-an owned value effectively throws it away directly afterwards, which is
-needlessly consuming code and heap space.
-
-### Example
-```
-if x.to_owned() == y {}
-```
-
-Use instead:
-```
-if x == y {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cognitive_complexity.txt b/src/tools/clippy/src/docs/cognitive_complexity.txt
deleted file mode 100644
index fdd75f6479c..00000000000
--- a/src/tools/clippy/src/docs/cognitive_complexity.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-### What it does
-Checks for methods with high cognitive complexity.
-
-### Why is this bad?
-Methods of high cognitive complexity tend to be hard to
-both read and maintain. Also LLVM will tend to optimize small methods better.
-
-### Known problems
-Sometimes it's hard to find a way to reduce the
-complexity.
-
-### Example
-You'll see it when you get the warning.
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/collapsible_else_if.txt b/src/tools/clippy/src/docs/collapsible_else_if.txt
deleted file mode 100644
index 4ddfca17731..00000000000
--- a/src/tools/clippy/src/docs/collapsible_else_if.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Checks for collapsible `else { if ... }` expressions
-that can be collapsed to `else if ...`.
-
-### Why is this bad?
-Each `if`-statement adds one level of nesting, which
-makes code look more complex than it really is.
-
-### Example
-```
-
-if x {
-    …
-} else {
-    if y {
-        …
-    }
-}
-```
-
-Should be written:
-
-```
-if x {
-    …
-} else if y {
-    …
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/collapsible_if.txt b/src/tools/clippy/src/docs/collapsible_if.txt
deleted file mode 100644
index e1264ee062e..00000000000
--- a/src/tools/clippy/src/docs/collapsible_if.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for nested `if` statements which can be collapsed
-by `&&`-combining their conditions.
-
-### Why is this bad?
-Each `if`-statement adds one level of nesting, which
-makes code look more complex than it really is.
-
-### Example
-```
-if x {
-    if y {
-        // …
-    }
-}
-```
-
-Use instead:
-```
-if x && y {
-    // …
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/collapsible_match.txt b/src/tools/clippy/src/docs/collapsible_match.txt
deleted file mode 100644
index 0d59594a03a..00000000000
--- a/src/tools/clippy/src/docs/collapsible_match.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-### What it does
-Finds nested `match` or `if let` expressions where the patterns may be "collapsed" together
-without adding any branches.
-
-Note that this lint is not intended to find _all_ cases where nested match patterns can be merged, but only
-cases where merging would most likely make the code more readable.
-
-### Why is this bad?
-It is unnecessarily verbose and complex.
-
-### Example
-```
-fn func(opt: Option<Result<u64, String>>) {
-    let n = match opt {
-        Some(n) => match n {
-            Ok(n) => n,
-            _ => return,
-        }
-        None => return,
-    };
-}
-```
-Use instead:
-```
-fn func(opt: Option<Result<u64, String>>) {
-    let n = match opt {
-        Some(Ok(n)) => n,
-        _ => return,
-    };
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/collapsible_str_replace.txt b/src/tools/clippy/src/docs/collapsible_str_replace.txt
deleted file mode 100644
index c24c25a3028..00000000000
--- a/src/tools/clippy/src/docs/collapsible_str_replace.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for consecutive calls to `str::replace` (2 or more)
-that can be collapsed into a single call.
-
-### Why is this bad?
-Consecutive `str::replace` calls scan the string multiple times
-with repetitive code.
-
-### Example
-```
-let hello = "hesuo worpd"
-    .replace('s', "l")
-    .replace("u", "l")
-    .replace('p', "l");
-```
-Use instead:
-```
-let hello = "hesuo worpd".replace(&['s', 'u', 'p'], "l");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/comparison_chain.txt b/src/tools/clippy/src/docs/comparison_chain.txt
deleted file mode 100644
index 43b09f31ff4..00000000000
--- a/src/tools/clippy/src/docs/comparison_chain.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-### What it does
-Checks comparison chains written with `if` that can be
-rewritten with `match` and `cmp`.
-
-### Why is this bad?
-`if` is not guaranteed to be exhaustive and conditionals can get
-repetitive
-
-### Known problems
-The match statement may be slower due to the compiler
-not inlining the call to cmp. See issue [#5354](https://github.com/rust-lang/rust-clippy/issues/5354)
-
-### Example
-```
-fn f(x: u8, y: u8) {
-    if x > y {
-        a()
-    } else if x < y {
-        b()
-    } else {
-        c()
-    }
-}
-```
-
-Use instead:
-```
-use std::cmp::Ordering;
-fn f(x: u8, y: u8) {
-     match x.cmp(&y) {
-         Ordering::Greater => a(),
-         Ordering::Less => b(),
-         Ordering::Equal => c()
-     }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/comparison_to_empty.txt b/src/tools/clippy/src/docs/comparison_to_empty.txt
deleted file mode 100644
index db6f74fe270..00000000000
--- a/src/tools/clippy/src/docs/comparison_to_empty.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-### What it does
-Checks for comparing to an empty slice such as `""` or `[]`,
-and suggests using `.is_empty()` where applicable.
-
-### Why is this bad?
-Some structures can answer `.is_empty()` much faster
-than checking for equality. So it is good to get into the habit of using
-`.is_empty()`, and having it is cheap.
-Besides, it makes the intent clearer than a manual comparison in some contexts.
-
-### Example
-
-```
-if s == "" {
-    ..
-}
-
-if arr == [] {
-    ..
-}
-```
-Use instead:
-```
-if s.is_empty() {
-    ..
-}
-
-if arr.is_empty() {
-    ..
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/copy_iterator.txt b/src/tools/clippy/src/docs/copy_iterator.txt
deleted file mode 100644
index 5f9a2a015b8..00000000000
--- a/src/tools/clippy/src/docs/copy_iterator.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for types that implement `Copy` as well as
-`Iterator`.
-
-### Why is this bad?
-Implicit copies can be confusing when working with
-iterator combinators.
-
-### Example
-```
-#[derive(Copy, Clone)]
-struct Countdown(u8);
-
-impl Iterator for Countdown {
-    // ...
-}
-
-let a: Vec<_> = my_iterator.take(1).collect();
-let b: Vec<_> = my_iterator.collect();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/crate_in_macro_def.txt b/src/tools/clippy/src/docs/crate_in_macro_def.txt
deleted file mode 100644
index 047e986dee7..00000000000
--- a/src/tools/clippy/src/docs/crate_in_macro_def.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-### What it does
-Checks for use of `crate` as opposed to `$crate` in a macro definition.
-
-### Why is this bad?
-`crate` refers to the macro call's crate, whereas `$crate` refers to the macro definition's
-crate. Rarely is the former intended. See:
-https://doc.rust-lang.org/reference/macros-by-example.html#hygiene
-
-### Example
-```
-#[macro_export]
-macro_rules! print_message {
-    () => {
-        println!("{}", crate::MESSAGE);
-    };
-}
-pub const MESSAGE: &str = "Hello!";
-```
-Use instead:
-```
-#[macro_export]
-macro_rules! print_message {
-    () => {
-        println!("{}", $crate::MESSAGE);
-    };
-}
-pub const MESSAGE: &str = "Hello!";
-```
-
-Note that if the use of `crate` is intentional, an `allow` attribute can be applied to the
-macro definition, e.g.:
-```
-#[allow(clippy::crate_in_macro_def)]
-macro_rules! ok { ... crate::foo ... }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/create_dir.txt b/src/tools/clippy/src/docs/create_dir.txt
deleted file mode 100644
index e4e7937684e..00000000000
--- a/src/tools/clippy/src/docs/create_dir.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks usage of `std::fs::create_dir` and suggest using `std::fs::create_dir_all` instead.
-
-### Why is this bad?
-Sometimes `std::fs::create_dir` is mistakenly chosen over `std::fs::create_dir_all`.
-
-### Example
-```
-std::fs::create_dir("foo");
-```
-
-Use instead:
-```
-std::fs::create_dir_all("foo");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/crosspointer_transmute.txt b/src/tools/clippy/src/docs/crosspointer_transmute.txt
deleted file mode 100644
index 49dea154970..00000000000
--- a/src/tools/clippy/src/docs/crosspointer_transmute.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for transmutes between a type `T` and `*T`.
-
-### Why is this bad?
-It's easy to mistakenly transmute between a type and a
-pointer to that type.
-
-### Example
-```
-core::intrinsics::transmute(t) // where the result type is the same as
-                               // `*t` or `&t`'s
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/dbg_macro.txt b/src/tools/clippy/src/docs/dbg_macro.txt
deleted file mode 100644
index 3e1a9a043f9..00000000000
--- a/src/tools/clippy/src/docs/dbg_macro.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for usage of dbg!() macro.
-
-### Why is this bad?
-`dbg!` macro is intended as a debugging tool. It
-should not be in version control.
-
-### Example
-```
-dbg!(true)
-```
-
-Use instead:
-```
-true
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/debug_assert_with_mut_call.txt b/src/tools/clippy/src/docs/debug_assert_with_mut_call.txt
deleted file mode 100644
index 2c44abe1f05..00000000000
--- a/src/tools/clippy/src/docs/debug_assert_with_mut_call.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for function/method calls with a mutable
-parameter in `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!` macros.
-
-### Why is this bad?
-In release builds `debug_assert!` macros are optimized out by the
-compiler.
-Therefore mutating something in a `debug_assert!` macro results in different behavior
-between a release and debug build.
-
-### Example
-```
-debug_assert_eq!(vec![3].pop(), Some(3));
-
-// or
-
-debug_assert!(takes_a_mut_parameter(&mut x));
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/decimal_literal_representation.txt b/src/tools/clippy/src/docs/decimal_literal_representation.txt
deleted file mode 100644
index daca9bbb3a8..00000000000
--- a/src/tools/clippy/src/docs/decimal_literal_representation.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-### What it does
-Warns if there is a better representation for a numeric literal.
-
-### Why is this bad?
-Especially for big powers of 2 a hexadecimal representation is more
-readable than a decimal representation.
-
-### Example
-```
-`255` => `0xFF`
-`65_535` => `0xFFFF`
-`4_042_322_160` => `0xF0F0_F0F0`
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/declare_interior_mutable_const.txt b/src/tools/clippy/src/docs/declare_interior_mutable_const.txt
deleted file mode 100644
index 2801b5ccff8..00000000000
--- a/src/tools/clippy/src/docs/declare_interior_mutable_const.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-### What it does
-Checks for declaration of `const` items which is interior
-mutable (e.g., contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.).
-
-### Why is this bad?
-Consts are copied everywhere they are referenced, i.e.,
-every time you refer to the const a fresh instance of the `Cell` or `Mutex`
-or `AtomicXxxx` will be created, which defeats the whole purpose of using
-these types in the first place.
-
-The `const` should better be replaced by a `static` item if a global
-variable is wanted, or replaced by a `const fn` if a constructor is wanted.
-
-### Known problems
-A "non-constant" const item is a legacy way to supply an
-initialized value to downstream `static` items (e.g., the
-`std::sync::ONCE_INIT` constant). In this case the use of `const` is legit,
-and this lint should be suppressed.
-
-Even though the lint avoids triggering on a constant whose type has enums that have variants
-with interior mutability, and its value uses non interior mutable variants (see
-[#3962](https://github.com/rust-lang/rust-clippy/issues/3962) and
-[#3825](https://github.com/rust-lang/rust-clippy/issues/3825) for examples);
-it complains about associated constants without default values only based on its types;
-which might not be preferable.
-There're other enums plus associated constants cases that the lint cannot handle.
-
-Types that have underlying or potential interior mutability trigger the lint whether
-the interior mutable field is used or not. See issues
-[#5812](https://github.com/rust-lang/rust-clippy/issues/5812) and
-
-### Example
-```
-use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
-
-const CONST_ATOM: AtomicUsize = AtomicUsize::new(12);
-CONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged
-assert_eq!(CONST_ATOM.load(SeqCst), 12); // because the CONST_ATOM in these lines are distinct
-```
-
-Use instead:
-```
-static STATIC_ATOM: AtomicUsize = AtomicUsize::new(15);
-STATIC_ATOM.store(9, SeqCst);
-assert_eq!(STATIC_ATOM.load(SeqCst), 9); // use a `static` item to refer to the same instance
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/default_instead_of_iter_empty.txt b/src/tools/clippy/src/docs/default_instead_of_iter_empty.txt
deleted file mode 100644
index b63ef3d18fc..00000000000
--- a/src/tools/clippy/src/docs/default_instead_of_iter_empty.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-It checks for `std::iter::Empty::default()` and suggests replacing it with
-`std::iter::empty()`.
-### Why is this bad?
-`std::iter::empty()` is the more idiomatic way.
-### Example
-```
-let _ = std::iter::Empty::<usize>::default();
-let iter: std::iter::Empty<usize> = std::iter::Empty::default();
-```
-Use instead:
-```
-let _ = std::iter::empty::<usize>();
-let iter: std::iter::Empty<usize> = std::iter::empty();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/default_numeric_fallback.txt b/src/tools/clippy/src/docs/default_numeric_fallback.txt
deleted file mode 100644
index 15076a0a68b..00000000000
--- a/src/tools/clippy/src/docs/default_numeric_fallback.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-### What it does
-Checks for usage of unconstrained numeric literals which may cause default numeric fallback in type
-inference.
-
-Default numeric fallback means that if numeric types have not yet been bound to concrete
-types at the end of type inference, then integer type is bound to `i32`, and similarly
-floating type is bound to `f64`.
-
-See [RFC0212](https://github.com/rust-lang/rfcs/blob/master/text/0212-restore-int-fallback.md) for more information about the fallback.
-
-### Why is this bad?
-For those who are very careful about types, default numeric fallback
-can be a pitfall that cause unexpected runtime behavior.
-
-### Known problems
-This lint can only be allowed at the function level or above.
-
-### Example
-```
-let i = 10;
-let f = 1.23;
-```
-
-Use instead:
-```
-let i = 10i32;
-let f = 1.23f64;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/default_trait_access.txt b/src/tools/clippy/src/docs/default_trait_access.txt
deleted file mode 100644
index e69298969c8..00000000000
--- a/src/tools/clippy/src/docs/default_trait_access.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for literal calls to `Default::default()`.
-
-### Why is this bad?
-It's easier for the reader if the name of the type is used, rather than the
-generic `Default`.
-
-### Example
-```
-let s: String = Default::default();
-```
-
-Use instead:
-```
-let s = String::default();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/default_union_representation.txt b/src/tools/clippy/src/docs/default_union_representation.txt
deleted file mode 100644
index f79ff9760e5..00000000000
--- a/src/tools/clippy/src/docs/default_union_representation.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-### What it does
-Displays a warning when a union is declared with the default representation (without a `#[repr(C)]` attribute).
-
-### Why is this bad?
-Unions in Rust have unspecified layout by default, despite many people thinking that they
-lay out each field at the start of the union (like C does). That is, there are no guarantees
-about the offset of the fields for unions with multiple non-ZST fields without an explicitly
-specified layout. These cases may lead to undefined behavior in unsafe blocks.
-
-### Example
-```
-union Foo {
-    a: i32,
-    b: u32,
-}
-
-fn main() {
-    let _x: u32 = unsafe {
-        Foo { a: 0_i32 }.b // Undefined behavior: `b` is allowed to be padding
-    };
-}
-```
-Use instead:
-```
-#[repr(C)]
-union Foo {
-    a: i32,
-    b: u32,
-}
-
-fn main() {
-    let _x: u32 = unsafe {
-        Foo { a: 0_i32 }.b // Now defined behavior, this is just an i32 -> u32 transmute
-    };
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/deprecated_cfg_attr.txt b/src/tools/clippy/src/docs/deprecated_cfg_attr.txt
deleted file mode 100644
index 9f264887a05..00000000000
--- a/src/tools/clippy/src/docs/deprecated_cfg_attr.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it
-with `#[rustfmt::skip]`.
-
-### Why is this bad?
-Since tool_attributes ([rust-lang/rust#44690](https://github.com/rust-lang/rust/issues/44690))
-are stable now, they should be used instead of the old `cfg_attr(rustfmt)` attributes.
-
-### Known problems
-This lint doesn't detect crate level inner attributes, because they get
-processed before the PreExpansionPass lints get executed. See
-[#3123](https://github.com/rust-lang/rust-clippy/pull/3123#issuecomment-422321765)
-
-### Example
-```
-#[cfg_attr(rustfmt, rustfmt_skip)]
-fn main() { }
-```
-
-Use instead:
-```
-#[rustfmt::skip]
-fn main() { }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/deprecated_semver.txt b/src/tools/clippy/src/docs/deprecated_semver.txt
deleted file mode 100644
index c9574a99b2b..00000000000
--- a/src/tools/clippy/src/docs/deprecated_semver.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-### What it does
-Checks for `#[deprecated]` annotations with a `since`
-field that is not a valid semantic version.
-
-### Why is this bad?
-For checking the version of the deprecation, it must be
-a valid semver. Failing that, the contained information is useless.
-
-### Example
-```
-#[deprecated(since = "forever")]
-fn something_else() { /* ... */ }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/deref_addrof.txt b/src/tools/clippy/src/docs/deref_addrof.txt
deleted file mode 100644
index fa711b924d4..00000000000
--- a/src/tools/clippy/src/docs/deref_addrof.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for usage of `*&` and `*&mut` in expressions.
-
-### Why is this bad?
-Immediately dereferencing a reference is no-op and
-makes the code less clear.
-
-### Known problems
-Multiple dereference/addrof pairs are not handled so
-the suggested fix for `x = **&&y` is `x = *&y`, which is still incorrect.
-
-### Example
-```
-let a = f(*&mut b);
-let c = *&d;
-```
-
-Use instead:
-```
-let a = f(b);
-let c = d;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/deref_by_slicing.txt b/src/tools/clippy/src/docs/deref_by_slicing.txt
deleted file mode 100644
index 4dad24ac00c..00000000000
--- a/src/tools/clippy/src/docs/deref_by_slicing.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for slicing expressions which are equivalent to dereferencing the
-value.
-
-### Why is this bad?
-Some people may prefer to dereference rather than slice.
-
-### Example
-```
-let vec = vec![1, 2, 3];
-let slice = &vec[..];
-```
-Use instead:
-```
-let vec = vec![1, 2, 3];
-let slice = &*vec;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/derivable_impls.txt b/src/tools/clippy/src/docs/derivable_impls.txt
deleted file mode 100644
index 5cee43956cc..00000000000
--- a/src/tools/clippy/src/docs/derivable_impls.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-### What it does
-Detects manual `std::default::Default` implementations that are identical to a derived implementation.
-
-### Why is this bad?
-It is less concise.
-
-### Example
-```
-struct Foo {
-    bar: bool
-}
-
-impl Default for Foo {
-    fn default() -> Self {
-        Self {
-            bar: false
-        }
-    }
-}
-```
-
-Use instead:
-```
-#[derive(Default)]
-struct Foo {
-    bar: bool
-}
-```
-
-### Known problems
-Derive macros [sometimes use incorrect bounds](https://github.com/rust-lang/rust/issues/26925)
-in generic types and the user defined `impl` may be more generalized or
-specialized than what derive will produce. This lint can't detect the manual `impl`
-has exactly equal bounds, and therefore this lint is disabled for types with
-generic parameters.
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/derive_hash_xor_eq.txt b/src/tools/clippy/src/docs/derive_hash_xor_eq.txt
deleted file mode 100644
index fbf623d5adb..00000000000
--- a/src/tools/clippy/src/docs/derive_hash_xor_eq.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for deriving `Hash` but implementing `PartialEq`
-explicitly or vice versa.
-
-### Why is this bad?
-The implementation of these traits must agree (for
-example for use with `HashMap`) so it’s probably a bad idea to use a
-default-generated `Hash` implementation with an explicitly defined
-`PartialEq`. In particular, the following must hold for any type:
-
-```
-k1 == k2 ⇒ hash(k1) == hash(k2)
-```
-
-### Example
-```
-#[derive(Hash)]
-struct Foo;
-
-impl PartialEq for Foo {
-    ...
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/derive_ord_xor_partial_ord.txt b/src/tools/clippy/src/docs/derive_ord_xor_partial_ord.txt
deleted file mode 100644
index f2107a5f69e..00000000000
--- a/src/tools/clippy/src/docs/derive_ord_xor_partial_ord.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-### What it does
-Checks for deriving `Ord` but implementing `PartialOrd`
-explicitly or vice versa.
-
-### Why is this bad?
-The implementation of these traits must agree (for
-example for use with `sort`) so it’s probably a bad idea to use a
-default-generated `Ord` implementation with an explicitly defined
-`PartialOrd`. In particular, the following must hold for any type
-implementing `Ord`:
-
-```
-k1.cmp(&k2) == k1.partial_cmp(&k2).unwrap()
-```
-
-### Example
-```
-#[derive(Ord, PartialEq, Eq)]
-struct Foo;
-
-impl PartialOrd for Foo {
-    ...
-}
-```
-Use instead:
-```
-#[derive(PartialEq, Eq)]
-struct Foo;
-
-impl PartialOrd for Foo {
-    fn partial_cmp(&self, other: &Foo) -> Option<Ordering> {
-       Some(self.cmp(other))
-    }
-}
-
-impl Ord for Foo {
-    ...
-}
-```
-or, if you don't need a custom ordering:
-```
-#[derive(Ord, PartialOrd, PartialEq, Eq)]
-struct Foo;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/derive_partial_eq_without_eq.txt b/src/tools/clippy/src/docs/derive_partial_eq_without_eq.txt
deleted file mode 100644
index 932fabad666..00000000000
--- a/src/tools/clippy/src/docs/derive_partial_eq_without_eq.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Checks for types that derive `PartialEq` and could implement `Eq`.
-
-### Why is this bad?
-If a type `T` derives `PartialEq` and all of its members implement `Eq`,
-then `T` can always implement `Eq`. Implementing `Eq` allows `T` to be used
-in APIs that require `Eq` types. It also allows structs containing `T` to derive
-`Eq` themselves.
-
-### Example
-```
-#[derive(PartialEq)]
-struct Foo {
-    i_am_eq: i32,
-    i_am_eq_too: Vec<String>,
-}
-```
-Use instead:
-```
-#[derive(PartialEq, Eq)]
-struct Foo {
-    i_am_eq: i32,
-    i_am_eq_too: Vec<String>,
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/disallowed_macros.txt b/src/tools/clippy/src/docs/disallowed_macros.txt
deleted file mode 100644
index 96fa15afabf..00000000000
--- a/src/tools/clippy/src/docs/disallowed_macros.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-### What it does
-Denies the configured macros in clippy.toml
-
-Note: Even though this lint is warn-by-default, it will only trigger if
-macros are defined in the clippy.toml file.
-
-### Why is this bad?
-Some macros are undesirable in certain contexts, and it's beneficial to
-lint for them as needed.
-
-### Example
-An example clippy.toml configuration:
-```
-disallowed-macros = [
-    # Can use a string as the path of the disallowed macro.
-    "std::print",
-    # Can also use an inline table with a `path` key.
-    { path = "std::println" },
-    # When using an inline table, can add a `reason` for why the macro
-    # is disallowed.
-    { path = "serde::Serialize", reason = "no serializing" },
-]
-```
-```
-use serde::Serialize;
-
-// Example code where clippy issues a warning
-println!("warns");
-
-// The diagnostic will contain the message "no serializing"
-#[derive(Serialize)]
-struct Data {
-    name: String,
-    value: usize,
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/disallowed_methods.txt b/src/tools/clippy/src/docs/disallowed_methods.txt
deleted file mode 100644
index d8ad5b6a667..00000000000
--- a/src/tools/clippy/src/docs/disallowed_methods.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-### What it does
-Denies the configured methods and functions in clippy.toml
-
-Note: Even though this lint is warn-by-default, it will only trigger if
-methods are defined in the clippy.toml file.
-
-### Why is this bad?
-Some methods are undesirable in certain contexts, and it's beneficial to
-lint for them as needed.
-
-### Example
-An example clippy.toml configuration:
-```
-disallowed-methods = [
-    # Can use a string as the path of the disallowed method.
-    "std::boxed::Box::new",
-    # Can also use an inline table with a `path` key.
-    { path = "std::time::Instant::now" },
-    # When using an inline table, can add a `reason` for why the method
-    # is disallowed.
-    { path = "std::vec::Vec::leak", reason = "no leaking memory" },
-]
-```
-
-```
-// Example code where clippy issues a warning
-let xs = vec![1, 2, 3, 4];
-xs.leak(); // Vec::leak is disallowed in the config.
-// The diagnostic contains the message "no leaking memory".
-
-let _now = Instant::now(); // Instant::now is disallowed in the config.
-
-let _box = Box::new(3); // Box::new is disallowed in the config.
-```
-
-Use instead:
-```
-// Example code which does not raise clippy warning
-let mut xs = Vec::new(); // Vec::new is _not_ disallowed in the config.
-xs.push(123); // Vec::push is _not_ disallowed in the config.
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/disallowed_names.txt b/src/tools/clippy/src/docs/disallowed_names.txt
deleted file mode 100644
index f4aaee9c77b..00000000000
--- a/src/tools/clippy/src/docs/disallowed_names.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for usage of disallowed names for variables, such
-as `foo`.
-
-### Why is this bad?
-These names are usually placeholder names and should be
-avoided.
-
-### Example
-```
-let foo = 3.14;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/disallowed_script_idents.txt b/src/tools/clippy/src/docs/disallowed_script_idents.txt
deleted file mode 100644
index 2151b7a20de..00000000000
--- a/src/tools/clippy/src/docs/disallowed_script_idents.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-### What it does
-Checks for usage of unicode scripts other than those explicitly allowed
-by the lint config.
-
-This lint doesn't take into account non-text scripts such as `Unknown` and `Linear_A`.
-It also ignores the `Common` script type.
-While configuring, be sure to use official script name [aliases] from
-[the list of supported scripts][supported_scripts].
-
-See also: [`non_ascii_idents`].
-
-[aliases]: http://www.unicode.org/reports/tr24/tr24-31.html#Script_Value_Aliases
-[supported_scripts]: https://www.unicode.org/iso15924/iso15924-codes.html
-
-### Why is this bad?
-It may be not desired to have many different scripts for
-identifiers in the codebase.
-
-Note that if you only want to allow plain English, you might want to use
-built-in [`non_ascii_idents`] lint instead.
-
-[`non_ascii_idents`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#non-ascii-idents
-
-### Example
-```
-// Assuming that `clippy.toml` contains the following line:
-// allowed-locales = ["Latin", "Cyrillic"]
-let counter = 10; // OK, latin is allowed.
-let счётчик = 10; // OK, cyrillic is allowed.
-let zähler = 10; // OK, it's still latin.
-let カウンタ = 10; // Will spawn the lint.
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/disallowed_types.txt b/src/tools/clippy/src/docs/disallowed_types.txt
deleted file mode 100644
index 2bcbcddee56..00000000000
--- a/src/tools/clippy/src/docs/disallowed_types.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-### What it does
-Denies the configured types in clippy.toml.
-
-Note: Even though this lint is warn-by-default, it will only trigger if
-types are defined in the clippy.toml file.
-
-### Why is this bad?
-Some types are undesirable in certain contexts.
-
-### Example:
-An example clippy.toml configuration:
-```
-disallowed-types = [
-    # Can use a string as the path of the disallowed type.
-    "std::collections::BTreeMap",
-    # Can also use an inline table with a `path` key.
-    { path = "std::net::TcpListener" },
-    # When using an inline table, can add a `reason` for why the type
-    # is disallowed.
-    { path = "std::net::Ipv4Addr", reason = "no IPv4 allowed" },
-]
-```
-
-```
-use std::collections::BTreeMap;
-// or its use
-let x = std::collections::BTreeMap::new();
-```
-Use instead:
-```
-// A similar type that is allowed by the config
-use std::collections::HashMap;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/diverging_sub_expression.txt b/src/tools/clippy/src/docs/diverging_sub_expression.txt
deleted file mode 100644
index 19436221802..00000000000
--- a/src/tools/clippy/src/docs/diverging_sub_expression.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for diverging calls that are not match arms or
-statements.
-
-### Why is this bad?
-It is often confusing to read. In addition, the
-sub-expression evaluation order for Rust is not well documented.
-
-### Known problems
-Someone might want to use `some_bool || panic!()` as a
-shorthand.
-
-### Example
-```
-let a = b() || panic!() || c();
-// `c()` is dead, `panic!()` is only called if `b()` returns `false`
-let x = (a, b, c, panic!());
-// can simply be replaced by `panic!()`
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/doc_link_with_quotes.txt b/src/tools/clippy/src/docs/doc_link_with_quotes.txt
deleted file mode 100644
index 107c8ac116d..00000000000
--- a/src/tools/clippy/src/docs/doc_link_with_quotes.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Detects the syntax `['foo']` in documentation comments (notice quotes instead of backticks)
-outside of code blocks
-### Why is this bad?
-It is likely a typo when defining an intra-doc link
-
-### Example
-```
-/// See also: ['foo']
-fn bar() {}
-```
-Use instead:
-```
-/// See also: [`foo`]
-fn bar() {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/doc_markdown.txt b/src/tools/clippy/src/docs/doc_markdown.txt
deleted file mode 100644
index 94f54c587e3..00000000000
--- a/src/tools/clippy/src/docs/doc_markdown.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-### What it does
-Checks for the presence of `_`, `::` or camel-case words
-outside ticks in documentation.
-
-### Why is this bad?
-*Rustdoc* supports markdown formatting, `_`, `::` and
-camel-case probably indicates some code which should be included between
-ticks. `_` can also be used for emphasis in markdown, this lint tries to
-consider that.
-
-### Known problems
-Lots of bad docs won’t be fixed, what the lint checks
-for is limited, and there are still false positives. HTML elements and their
-content are not linted.
-
-In addition, when writing documentation comments, including `[]` brackets
-inside a link text would trip the parser. Therefore, documenting link with
-`[`SmallVec<[T; INLINE_CAPACITY]>`]` and then [`SmallVec<[T; INLINE_CAPACITY]>`]: SmallVec
-would fail.
-
-### Examples
-```
-/// Do something with the foo_bar parameter. See also
-/// that::other::module::foo.
-// ^ `foo_bar` and `that::other::module::foo` should be ticked.
-fn doit(foo_bar: usize) {}
-```
-
-```
-// Link text with `[]` brackets should be written as following:
-/// Consume the array and return the inner
-/// [`SmallVec<[T; INLINE_CAPACITY]>`][SmallVec].
-/// [SmallVec]: SmallVec
-fn main() {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/double_comparisons.txt b/src/tools/clippy/src/docs/double_comparisons.txt
deleted file mode 100644
index 7dc6818779f..00000000000
--- a/src/tools/clippy/src/docs/double_comparisons.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for double comparisons that could be simplified to a single expression.
-
-
-### Why is this bad?
-Readability.
-
-### Example
-```
-if x == y || x < y {}
-```
-
-Use instead:
-
-```
-if x <= y {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/double_must_use.txt b/src/tools/clippy/src/docs/double_must_use.txt
deleted file mode 100644
index 0017d10d40d..00000000000
--- a/src/tools/clippy/src/docs/double_must_use.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for a `#[must_use]` attribute without
-further information on functions and methods that return a type already
-marked as `#[must_use]`.
-
-### Why is this bad?
-The attribute isn't needed. Not using the result
-will already be reported. Alternatively, one can add some text to the
-attribute to improve the lint message.
-
-### Examples
-```
-#[must_use]
-fn double_must_use() -> Result<(), ()> {
-    unimplemented!();
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/double_neg.txt b/src/tools/clippy/src/docs/double_neg.txt
deleted file mode 100644
index a07f67496d7..00000000000
--- a/src/tools/clippy/src/docs/double_neg.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Detects expressions of the form `--x`.
-
-### Why is this bad?
-It can mislead C/C++ programmers to think `x` was
-decremented.
-
-### Example
-```
-let mut x = 3;
---x;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/double_parens.txt b/src/tools/clippy/src/docs/double_parens.txt
deleted file mode 100644
index 260d7dd575e..00000000000
--- a/src/tools/clippy/src/docs/double_parens.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for unnecessary double parentheses.
-
-### Why is this bad?
-This makes code harder to read and might indicate a
-mistake.
-
-### Example
-```
-fn simple_double_parens() -> i32 {
-    ((0))
-}
-
-foo((0));
-```
-
-Use instead:
-```
-fn simple_no_parens() -> i32 {
-    0
-}
-
-foo(0);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/drop_copy.txt b/src/tools/clippy/src/docs/drop_copy.txt
deleted file mode 100644
index f917ca8ed21..00000000000
--- a/src/tools/clippy/src/docs/drop_copy.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### 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
-```
-let x: i32 = 42; // i32 implements Copy
-std::mem::drop(x) // A copy of x is passed to the function, leaving the
-                  // original unaffected
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/drop_non_drop.txt b/src/tools/clippy/src/docs/drop_non_drop.txt
deleted file mode 100644
index ee1e3a6c216..00000000000
--- a/src/tools/clippy/src/docs/drop_non_drop.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-### What it does
-Checks for calls to `std::mem::drop` with a value that does not implement `Drop`.
-
-### Why is this bad?
-Calling `std::mem::drop` is no different than dropping such a type. A different value may
-have been intended.
-
-### Example
-```
-struct Foo;
-let x = Foo;
-std::mem::drop(x);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/drop_ref.txt b/src/tools/clippy/src/docs/drop_ref.txt
deleted file mode 100644
index c4f7adf0cfa..00000000000
--- a/src/tools/clippy/src/docs/drop_ref.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### 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
-```
-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();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/duplicate_mod.txt b/src/tools/clippy/src/docs/duplicate_mod.txt
deleted file mode 100644
index 709a9aba03a..00000000000
--- a/src/tools/clippy/src/docs/duplicate_mod.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-### What it does
-Checks for files that are included as modules multiple times.
-
-### Why is this bad?
-Loading a file as a module more than once causes it to be compiled
-multiple times, taking longer and putting duplicate content into the
-module tree.
-
-### Example
-```
-// lib.rs
-mod a;
-mod b;
-```
-```
-// a.rs
-#[path = "./b.rs"]
-mod b;
-```
-
-Use instead:
-
-```
-// lib.rs
-mod a;
-mod b;
-```
-```
-// a.rs
-use crate::b;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/duplicate_underscore_argument.txt b/src/tools/clippy/src/docs/duplicate_underscore_argument.txt
deleted file mode 100644
index a8fcd6a9fbe..00000000000
--- a/src/tools/clippy/src/docs/duplicate_underscore_argument.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for function arguments having the similar names
-differing by an underscore.
-
-### Why is this bad?
-It affects code readability.
-
-### Example
-```
-fn foo(a: i32, _a: i32) {}
-```
-
-Use instead:
-```
-fn bar(a: i32, _b: i32) {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/duration_subsec.txt b/src/tools/clippy/src/docs/duration_subsec.txt
deleted file mode 100644
index e7e0ca88745..00000000000
--- a/src/tools/clippy/src/docs/duration_subsec.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for calculation of subsecond microseconds or milliseconds
-from other `Duration` methods.
-
-### Why is this bad?
-It's more concise to call `Duration::subsec_micros()` or
-`Duration::subsec_millis()` than to calculate them.
-
-### Example
-```
-let micros = duration.subsec_nanos() / 1_000;
-let millis = duration.subsec_nanos() / 1_000_000;
-```
-
-Use instead:
-```
-let micros = duration.subsec_micros();
-let millis = duration.subsec_millis();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/else_if_without_else.txt b/src/tools/clippy/src/docs/else_if_without_else.txt
deleted file mode 100644
index 33f5d0f9185..00000000000
--- a/src/tools/clippy/src/docs/else_if_without_else.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for usage of if expressions with an `else if` branch,
-but without a final `else` branch.
-
-### Why is this bad?
-Some coding guidelines require this (e.g., MISRA-C:2004 Rule 14.10).
-
-### Example
-```
-if x.is_positive() {
-    a();
-} else if x.is_negative() {
-    b();
-}
-```
-
-Use instead:
-
-```
-if x.is_positive() {
-    a();
-} else if x.is_negative() {
-    b();
-} else {
-    // We don't care about zero.
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/empty_drop.txt b/src/tools/clippy/src/docs/empty_drop.txt
deleted file mode 100644
index d0c0c24a9c8..00000000000
--- a/src/tools/clippy/src/docs/empty_drop.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for empty `Drop` implementations.
-
-### Why is this bad?
-Empty `Drop` implementations have no effect when dropping an instance of the type. They are
-most likely useless. However, an empty `Drop` implementation prevents a type from being
-destructured, which might be the intention behind adding the implementation as a marker.
-
-### Example
-```
-struct S;
-
-impl Drop for S {
-    fn drop(&mut self) {}
-}
-```
-Use instead:
-```
-struct S;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/empty_enum.txt b/src/tools/clippy/src/docs/empty_enum.txt
deleted file mode 100644
index f7b41c41ee5..00000000000
--- a/src/tools/clippy/src/docs/empty_enum.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for `enum`s with no variants.
-
-As of this writing, the `never_type` is still a
-nightly-only experimental API. Therefore, this lint is only triggered
-if the `never_type` is enabled.
-
-### Why is this bad?
-If you want to introduce a type which
-can't be instantiated, you should use `!` (the primitive type "never"),
-or a wrapper around it, because `!` has more extensive
-compiler support (type inference, etc...) and wrappers
-around it are the conventional way to define an uninhabited type.
-For further information visit [never type documentation](https://doc.rust-lang.org/std/primitive.never.html)
-
-
-### Example
-```
-enum Test {}
-```
-
-Use instead:
-```
-#![feature(never_type)]
-
-struct Test(!);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/empty_line_after_outer_attr.txt b/src/tools/clippy/src/docs/empty_line_after_outer_attr.txt
deleted file mode 100644
index c85242bbee0..00000000000
--- a/src/tools/clippy/src/docs/empty_line_after_outer_attr.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-### What it does
-Checks for empty lines after outer attributes
-
-### Why is this bad?
-Most likely the attribute was meant to be an inner attribute using a '!'.
-If it was meant to be an outer attribute, then the following item
-should not be separated by empty lines.
-
-### Known problems
-Can cause false positives.
-
-From the clippy side it's difficult to detect empty lines between an attributes and the
-following item because empty lines and comments are not part of the AST. The parsing
-currently works for basic cases but is not perfect.
-
-### Example
-```
-#[allow(dead_code)]
-
-fn not_quite_good_code() { }
-```
-
-Use instead:
-```
-// Good (as inner attribute)
-#![allow(dead_code)]
-
-fn this_is_fine() { }
-
-// or
-
-// Good (as outer attribute)
-#[allow(dead_code)]
-fn this_is_fine_too() { }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/empty_loop.txt b/src/tools/clippy/src/docs/empty_loop.txt
deleted file mode 100644
index fea49a74d04..00000000000
--- a/src/tools/clippy/src/docs/empty_loop.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for empty `loop` expressions.
-
-### Why is this bad?
-These busy loops burn CPU cycles without doing
-anything. It is _almost always_ a better idea to `panic!` than to have
-a busy loop.
-
-If panicking isn't possible, think of the environment and either:
-  - block on something
-  - sleep the thread for some microseconds
-  - yield or pause the thread
-
-For `std` targets, this can be done with
-[`std::thread::sleep`](https://doc.rust-lang.org/std/thread/fn.sleep.html)
-or [`std::thread::yield_now`](https://doc.rust-lang.org/std/thread/fn.yield_now.html).
-
-For `no_std` targets, doing this is more complicated, especially because
-`#[panic_handler]`s can't panic. To stop/pause the thread, you will
-probably need to invoke some target-specific intrinsic. Examples include:
-  - [`x86_64::instructions::hlt`](https://docs.rs/x86_64/0.12.2/x86_64/instructions/fn.hlt.html)
-  - [`cortex_m::asm::wfi`](https://docs.rs/cortex-m/0.6.3/cortex_m/asm/fn.wfi.html)
-
-### Example
-```
-loop {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/empty_structs_with_brackets.txt b/src/tools/clippy/src/docs/empty_structs_with_brackets.txt
deleted file mode 100644
index ab5e35ae2ad..00000000000
--- a/src/tools/clippy/src/docs/empty_structs_with_brackets.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Finds structs without fields (a so-called "empty struct") that are declared with brackets.
-
-### Why is this bad?
-Empty brackets after a struct declaration can be omitted.
-
-### Example
-```
-struct Cookie {}
-```
-Use instead:
-```
-struct Cookie;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/enum_clike_unportable_variant.txt b/src/tools/clippy/src/docs/enum_clike_unportable_variant.txt
deleted file mode 100644
index d30a973a5a1..00000000000
--- a/src/tools/clippy/src/docs/enum_clike_unportable_variant.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for C-like enumerations that are
-`repr(isize/usize)` and have values that don't fit into an `i32`.
-
-### Why is this bad?
-This will truncate the variant value on 32 bit
-architectures, but works fine on 64 bit.
-
-### Example
-```
-#[repr(usize)]
-enum NonPortable {
-    X = 0x1_0000_0000,
-    Y = 0,
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/enum_glob_use.txt b/src/tools/clippy/src/docs/enum_glob_use.txt
deleted file mode 100644
index 3776822c35b..00000000000
--- a/src/tools/clippy/src/docs/enum_glob_use.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for `use Enum::*`.
-
-### Why is this bad?
-It is usually better style to use the prefixed name of
-an enumeration variant, rather than importing variants.
-
-### Known problems
-Old-style enumerations that prefix the variants are
-still around.
-
-### Example
-```
-use std::cmp::Ordering::*;
-
-foo(Less);
-```
-
-Use instead:
-```
-use std::cmp::Ordering;
-
-foo(Ordering::Less)
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/enum_variant_names.txt b/src/tools/clippy/src/docs/enum_variant_names.txt
deleted file mode 100644
index e726925edda..00000000000
--- a/src/tools/clippy/src/docs/enum_variant_names.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-### What it does
-Detects enumeration variants that are prefixed or suffixed
-by the same characters.
-
-### Why is this bad?
-Enumeration variant names should specify their variant,
-not repeat the enumeration name.
-
-### Limitations
-Characters with no casing will be considered when comparing prefixes/suffixes
-This applies to numbers and non-ascii characters without casing
-e.g. `Foo1` and `Foo2` is considered to have different prefixes
-(the prefixes are `Foo1` and `Foo2` respectively), as also `Bar螃`, `Bar蟹`
-
-### Example
-```
-enum Cake {
-    BlackForestCake,
-    HummingbirdCake,
-    BattenbergCake,
-}
-```
-Use instead:
-```
-enum Cake {
-    BlackForest,
-    Hummingbird,
-    Battenberg,
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/eq_op.txt b/src/tools/clippy/src/docs/eq_op.txt
deleted file mode 100644
index 2d75a0ec546..00000000000
--- a/src/tools/clippy/src/docs/eq_op.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for equal operands to comparison, logical and
-bitwise, difference and division binary operators (`==`, `>`, etc., `&&`,
-`||`, `&`, `|`, `^`, `-` and `/`).
-
-### Why is this bad?
-This is usually just a typo or a copy and paste error.
-
-### Known problems
-False negatives: We had some false positives regarding
-calls (notably [racer](https://github.com/phildawes/racer) had one instance
-of `x.pop() && x.pop()`), so we removed matching any function or method
-calls. We may introduce a list of known pure functions in the future.
-
-### Example
-```
-if x + 1 == x + 1 {}
-
-// or
-
-assert_eq!(a, a);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/equatable_if_let.txt b/src/tools/clippy/src/docs/equatable_if_let.txt
deleted file mode 100644
index 9997046954c..00000000000
--- a/src/tools/clippy/src/docs/equatable_if_let.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for pattern matchings that can be expressed using equality.
-
-### Why is this bad?
-
-* It reads better and has less cognitive load because equality won't cause binding.
-* It is a [Yoda condition](https://en.wikipedia.org/wiki/Yoda_conditions). Yoda conditions are widely
-criticized for increasing the cognitive load of reading the code.
-* Equality is a simple bool expression and can be merged with `&&` and `||` and
-reuse if blocks
-
-### Example
-```
-if let Some(2) = x {
-    do_thing();
-}
-```
-Use instead:
-```
-if x == Some(2) {
-    do_thing();
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/erasing_op.txt b/src/tools/clippy/src/docs/erasing_op.txt
deleted file mode 100644
index 3d285a6d86e..00000000000
--- a/src/tools/clippy/src/docs/erasing_op.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for erasing operations, e.g., `x * 0`.
-
-### Why is this bad?
-The whole expression can be replaced by zero.
-This is most likely not the intended outcome and should probably be
-corrected
-
-### Example
-```
-let x = 1;
-0 / x;
-0 * x;
-x & 0;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/err_expect.txt b/src/tools/clippy/src/docs/err_expect.txt
deleted file mode 100644
index 1dc83c5ce0e..00000000000
--- a/src/tools/clippy/src/docs/err_expect.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for `.err().expect()` calls on the `Result` type.
-
-### Why is this bad?
-`.expect_err()` can be called directly to avoid the extra type conversion from `err()`.
-
-### Example
-```
-let x: Result<u32, &str> = Ok(10);
-x.err().expect("Testing err().expect()");
-```
-Use instead:
-```
-let x: Result<u32, &str> = Ok(10);
-x.expect_err("Testing expect_err");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/excessive_precision.txt b/src/tools/clippy/src/docs/excessive_precision.txt
deleted file mode 100644
index 517879c4715..00000000000
--- a/src/tools/clippy/src/docs/excessive_precision.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for float literals with a precision greater
-than that supported by the underlying type.
-
-### Why is this bad?
-Rust will truncate the literal silently.
-
-### Example
-```
-let v: f32 = 0.123_456_789_9;
-println!("{}", v); //  0.123_456_789
-```
-
-Use instead:
-```
-let v: f64 = 0.123_456_789_9;
-println!("{}", v); //  0.123_456_789_9
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/exhaustive_enums.txt b/src/tools/clippy/src/docs/exhaustive_enums.txt
deleted file mode 100644
index d1032a7a29a..00000000000
--- a/src/tools/clippy/src/docs/exhaustive_enums.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Warns on any exported `enum`s that are not tagged `#[non_exhaustive]`
-
-### Why is this bad?
-Exhaustive enums are typically fine, but a project which does
-not wish to make a stability commitment around exported enums may wish to
-disable them by default.
-
-### Example
-```
-enum Foo {
-    Bar,
-    Baz
-}
-```
-Use instead:
-```
-#[non_exhaustive]
-enum Foo {
-    Bar,
-    Baz
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/exhaustive_structs.txt b/src/tools/clippy/src/docs/exhaustive_structs.txt
deleted file mode 100644
index fd6e4f5caf1..00000000000
--- a/src/tools/clippy/src/docs/exhaustive_structs.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Warns on any exported `structs`s that are not tagged `#[non_exhaustive]`
-
-### Why is this bad?
-Exhaustive structs are typically fine, but a project which does
-not wish to make a stability commitment around exported structs may wish to
-disable them by default.
-
-### Example
-```
-struct Foo {
-    bar: u8,
-    baz: String,
-}
-```
-Use instead:
-```
-#[non_exhaustive]
-struct Foo {
-    bar: u8,
-    baz: String,
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/exit.txt b/src/tools/clippy/src/docs/exit.txt
deleted file mode 100644
index 1e6154d43e0..00000000000
--- a/src/tools/clippy/src/docs/exit.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-`exit()`  terminates the program and doesn't provide a
-stack trace.
-
-### Why is this bad?
-Ideally a program is terminated by finishing
-the main function.
-
-### Example
-```
-std::process::exit(0)
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/expect_fun_call.txt b/src/tools/clippy/src/docs/expect_fun_call.txt
deleted file mode 100644
index d82d9aa9baf..00000000000
--- a/src/tools/clippy/src/docs/expect_fun_call.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for calls to `.expect(&format!(...))`, `.expect(foo(..))`,
-etc., and suggests to use `unwrap_or_else` instead
-
-### Why is this bad?
-The function will always be called.
-
-### Known problems
-If the function has side-effects, not calling it will
-change the semantics of the program, but you shouldn't rely on that anyway.
-
-### Example
-```
-foo.expect(&format!("Err {}: {}", err_code, err_msg));
-
-// or
-
-foo.expect(format!("Err {}: {}", err_code, err_msg).as_str());
-```
-
-Use instead:
-```
-foo.unwrap_or_else(|| panic!("Err {}: {}", err_code, err_msg));
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/expect_used.txt b/src/tools/clippy/src/docs/expect_used.txt
deleted file mode 100644
index 4a6981e334f..00000000000
--- a/src/tools/clippy/src/docs/expect_used.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for `.expect()` or `.expect_err()` calls on `Result`s and `.expect()` call on `Option`s.
-
-### Why is this bad?
-Usually it is better to handle the `None` or `Err` case.
-Still, for a lot of quick-and-dirty code, `expect` is a good choice, which is why
-this lint is `Allow` by default.
-
-`result.expect()` will let the thread panic on `Err`
-values. Normally, you want to implement more sophisticated error handling,
-and propagate errors upwards with `?` operator.
-
-### Examples
-```
-option.expect("one");
-result.expect("one");
-```
-
-Use instead:
-```
-option?;
-
-// or
-
-result?;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/expl_impl_clone_on_copy.txt b/src/tools/clippy/src/docs/expl_impl_clone_on_copy.txt
deleted file mode 100644
index 391d93b6713..00000000000
--- a/src/tools/clippy/src/docs/expl_impl_clone_on_copy.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for explicit `Clone` implementations for `Copy`
-types.
-
-### Why is this bad?
-To avoid surprising behavior, these traits should
-agree and the behavior of `Copy` cannot be overridden. In almost all
-situations a `Copy` type should have a `Clone` implementation that does
-nothing more than copy the object, which is what `#[derive(Copy, Clone)]`
-gets you.
-
-### Example
-```
-#[derive(Copy)]
-struct Foo;
-
-impl Clone for Foo {
-    // ..
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/explicit_auto_deref.txt b/src/tools/clippy/src/docs/explicit_auto_deref.txt
deleted file mode 100644
index 65b25631772..00000000000
--- a/src/tools/clippy/src/docs/explicit_auto_deref.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for dereferencing expressions which would be covered by auto-deref.
-
-### Why is this bad?
-This unnecessarily complicates the code.
-
-### Example
-```
-let x = String::new();
-let y: &str = &*x;
-```
-Use instead:
-```
-let x = String::new();
-let y: &str = &x;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/explicit_counter_loop.txt b/src/tools/clippy/src/docs/explicit_counter_loop.txt
deleted file mode 100644
index 2661a43e103..00000000000
--- a/src/tools/clippy/src/docs/explicit_counter_loop.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks `for` loops over slices with an explicit counter
-and suggests the use of `.enumerate()`.
-
-### Why is this bad?
-Using `.enumerate()` makes the intent more clear,
-declutters the code and may be faster in some instances.
-
-### Example
-```
-let mut i = 0;
-for item in &v {
-    bar(i, *item);
-    i += 1;
-}
-```
-
-Use instead:
-```
-for (i, item) in v.iter().enumerate() { bar(i, *item); }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/explicit_deref_methods.txt b/src/tools/clippy/src/docs/explicit_deref_methods.txt
deleted file mode 100644
index e14e981c707..00000000000
--- a/src/tools/clippy/src/docs/explicit_deref_methods.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for explicit `deref()` or `deref_mut()` method calls.
-
-### Why is this bad?
-Dereferencing by `&*x` or `&mut *x` is clearer and more concise,
-when not part of a method chain.
-
-### Example
-```
-use std::ops::Deref;
-let a: &mut String = &mut String::from("foo");
-let b: &str = a.deref();
-```
-
-Use instead:
-```
-let a: &mut String = &mut String::from("foo");
-let b = &*a;
-```
-
-This lint excludes:
-```
-let _ = d.unwrap().deref();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/explicit_into_iter_loop.txt b/src/tools/clippy/src/docs/explicit_into_iter_loop.txt
deleted file mode 100644
index 3931dfd69a3..00000000000
--- a/src/tools/clippy/src/docs/explicit_into_iter_loop.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for loops on `y.into_iter()` where `y` will do, and
-suggests the latter.
-
-### Why is this bad?
-Readability.
-
-### Example
-```
-// with `y` a `Vec` or slice:
-for x in y.into_iter() {
-    // ..
-}
-```
-can be rewritten to
-```
-for x in y {
-    // ..
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/explicit_iter_loop.txt b/src/tools/clippy/src/docs/explicit_iter_loop.txt
deleted file mode 100644
index cabe72e91d0..00000000000
--- a/src/tools/clippy/src/docs/explicit_iter_loop.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Checks for loops on `x.iter()` where `&x` will do, and
-suggests the latter.
-
-### Why is this bad?
-Readability.
-
-### Known problems
-False negatives. We currently only warn on some known
-types.
-
-### Example
-```
-// with `y` a `Vec` or slice:
-for x in y.iter() {
-    // ..
-}
-```
-
-Use instead:
-```
-for x in &y {
-    // ..
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/explicit_write.txt b/src/tools/clippy/src/docs/explicit_write.txt
deleted file mode 100644
index eafed5d39e5..00000000000
--- a/src/tools/clippy/src/docs/explicit_write.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for usage of `write!()` / `writeln()!` which can be
-replaced with `(e)print!()` / `(e)println!()`
-
-### Why is this bad?
-Using `(e)println! is clearer and more concise
-
-### Example
-```
-writeln!(&mut std::io::stderr(), "foo: {:?}", bar).unwrap();
-writeln!(&mut std::io::stdout(), "foo: {:?}", bar).unwrap();
-```
-
-Use instead:
-```
-eprintln!("foo: {:?}", bar);
-println!("foo: {:?}", bar);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/extend_with_drain.txt b/src/tools/clippy/src/docs/extend_with_drain.txt
deleted file mode 100644
index 2f31dcf5f74..00000000000
--- a/src/tools/clippy/src/docs/extend_with_drain.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for occurrences where one vector gets extended instead of append
-
-### Why is this bad?
-Using `append` instead of `extend` is more concise and faster
-
-### Example
-```
-let mut a = vec![1, 2, 3];
-let mut b = vec![4, 5, 6];
-
-a.extend(b.drain(..));
-```
-
-Use instead:
-```
-let mut a = vec![1, 2, 3];
-let mut b = vec![4, 5, 6];
-
-a.append(&mut b);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/extra_unused_lifetimes.txt b/src/tools/clippy/src/docs/extra_unused_lifetimes.txt
deleted file mode 100644
index bc1814aa475..00000000000
--- a/src/tools/clippy/src/docs/extra_unused_lifetimes.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for lifetimes in generics that are never used
-anywhere else.
-
-### Why is this bad?
-The additional lifetimes make the code look more
-complicated, while there is nothing out of the ordinary going on. Removing
-them leads to more readable code.
-
-### Example
-```
-// unnecessary lifetimes
-fn unused_lifetime<'a>(x: u8) {
-    // ..
-}
-```
-
-Use instead:
-```
-fn no_lifetime(x: u8) {
-    // ...
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/fallible_impl_from.txt b/src/tools/clippy/src/docs/fallible_impl_from.txt
deleted file mode 100644
index 588a5bb103d..00000000000
--- a/src/tools/clippy/src/docs/fallible_impl_from.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-### What it does
-Checks for impls of `From<..>` that contain `panic!()` or `unwrap()`
-
-### Why is this bad?
-`TryFrom` should be used if there's a possibility of failure.
-
-### Example
-```
-struct Foo(i32);
-
-impl From<String> for Foo {
-    fn from(s: String) -> Self {
-        Foo(s.parse().unwrap())
-    }
-}
-```
-
-Use instead:
-```
-struct Foo(i32);
-
-impl TryFrom<String> for Foo {
-    type Error = ();
-    fn try_from(s: String) -> Result<Self, Self::Error> {
-        if let Ok(parsed) = s.parse() {
-            Ok(Foo(parsed))
-        } else {
-            Err(())
-        }
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/field_reassign_with_default.txt b/src/tools/clippy/src/docs/field_reassign_with_default.txt
deleted file mode 100644
index e58b7239fde..00000000000
--- a/src/tools/clippy/src/docs/field_reassign_with_default.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for immediate reassignment of fields initialized
-with Default::default().
-
-### Why is this bad?
-It's more idiomatic to use the [functional update syntax](https://doc.rust-lang.org/reference/expressions/struct-expr.html#functional-update-syntax).
-
-### Known problems
-Assignments to patterns that are of tuple type are not linted.
-
-### Example
-```
-let mut a: A = Default::default();
-a.i = 42;
-```
-
-Use instead:
-```
-let a = A {
-    i: 42,
-    .. Default::default()
-};
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/filetype_is_file.txt b/src/tools/clippy/src/docs/filetype_is_file.txt
deleted file mode 100644
index ad14bd62c4d..00000000000
--- a/src/tools/clippy/src/docs/filetype_is_file.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Checks for `FileType::is_file()`.
-
-### Why is this bad?
-When people testing a file type with `FileType::is_file`
-they are testing whether a path is something they can get bytes from. But
-`is_file` doesn't cover special file types in unix-like systems, and doesn't cover
-symlink in windows. Using `!FileType::is_dir()` is a better way to that intention.
-
-### Example
-```
-let metadata = std::fs::metadata("foo.txt")?;
-let filetype = metadata.file_type();
-
-if filetype.is_file() {
-    // read file
-}
-```
-
-should be written as:
-
-```
-let metadata = std::fs::metadata("foo.txt")?;
-let filetype = metadata.file_type();
-
-if !filetype.is_dir() {
-    // read file
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/filter_map_identity.txt b/src/tools/clippy/src/docs/filter_map_identity.txt
deleted file mode 100644
index 83b666f2e27..00000000000
--- a/src/tools/clippy/src/docs/filter_map_identity.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Checks for usage of `filter_map(|x| x)`.
-
-### Why is this bad?
-Readability, this can be written more concisely by using `flatten`.
-
-### Example
-```
-iter.filter_map(|x| x);
-```
-Use instead:
-```
-iter.flatten();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/filter_map_next.txt b/src/tools/clippy/src/docs/filter_map_next.txt
deleted file mode 100644
index b38620b56a5..00000000000
--- a/src/tools/clippy/src/docs/filter_map_next.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for usage of `_.filter_map(_).next()`.
-
-### Why is this bad?
-Readability, this can be written more concisely as
-`_.find_map(_)`.
-
-### Example
-```
- (0..3).filter_map(|x| if x == 2 { Some(x) } else { None }).next();
-```
-Can be written as
-
-```
- (0..3).find_map(|x| if x == 2 { Some(x) } else { None });
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/filter_next.txt b/src/tools/clippy/src/docs/filter_next.txt
deleted file mode 100644
index 898a74166dc..00000000000
--- a/src/tools/clippy/src/docs/filter_next.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for usage of `_.filter(_).next()`.
-
-### Why is this bad?
-Readability, this can be written more concisely as
-`_.find(_)`.
-
-### Example
-```
-vec.iter().filter(|x| **x == 0).next();
-```
-
-Use instead:
-```
-vec.iter().find(|x| **x == 0);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/flat_map_identity.txt b/src/tools/clippy/src/docs/flat_map_identity.txt
deleted file mode 100644
index a5ee79b4982..00000000000
--- a/src/tools/clippy/src/docs/flat_map_identity.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Checks for usage of `flat_map(|x| x)`.
-
-### Why is this bad?
-Readability, this can be written more concisely by using `flatten`.
-
-### Example
-```
-iter.flat_map(|x| x);
-```
-Can be written as
-```
-iter.flatten();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/flat_map_option.txt b/src/tools/clippy/src/docs/flat_map_option.txt
deleted file mode 100644
index d50b9156d36..00000000000
--- a/src/tools/clippy/src/docs/flat_map_option.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for usages of `Iterator::flat_map()` where `filter_map()` could be
-used instead.
-
-### Why is this bad?
-When applicable, `filter_map()` is more clear since it shows that
-`Option` is used to produce 0 or 1 items.
-
-### Example
-```
-let nums: Vec<i32> = ["1", "2", "whee!"].iter().flat_map(|x| x.parse().ok()).collect();
-```
-Use instead:
-```
-let nums: Vec<i32> = ["1", "2", "whee!"].iter().filter_map(|x| x.parse().ok()).collect();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/float_arithmetic.txt b/src/tools/clippy/src/docs/float_arithmetic.txt
deleted file mode 100644
index 1f9bce5abd5..00000000000
--- a/src/tools/clippy/src/docs/float_arithmetic.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-### What it does
-Checks for float arithmetic.
-
-### Why is this bad?
-For some embedded systems or kernel development, it
-can be useful to rule out floating-point numbers.
-
-### Example
-```
-a + 1.0;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/float_cmp.txt b/src/tools/clippy/src/docs/float_cmp.txt
deleted file mode 100644
index c19907c903e..00000000000
--- a/src/tools/clippy/src/docs/float_cmp.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-### What it does
-Checks for (in-)equality comparisons on floating-point
-values (apart from zero), except in functions called `*eq*` (which probably
-implement equality for a type involving floats).
-
-### Why is this bad?
-Floating point calculations are usually imprecise, so
-asking if two values are *exactly* equal is asking for trouble. For a good
-guide on what to do, see [the floating point
-guide](http://www.floating-point-gui.de/errors/comparison).
-
-### Example
-```
-let x = 1.2331f64;
-let y = 1.2332f64;
-
-if y == 1.23f64 { }
-if y != x {} // where both are floats
-```
-
-Use instead:
-```
-let error_margin = f64::EPSILON; // Use an epsilon for comparison
-// Or, if Rust <= 1.42, use `std::f64::EPSILON` constant instead.
-// let error_margin = std::f64::EPSILON;
-if (y - 1.23f64).abs() < error_margin { }
-if (y - x).abs() > error_margin { }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/float_cmp_const.txt b/src/tools/clippy/src/docs/float_cmp_const.txt
deleted file mode 100644
index 9208feaacd8..00000000000
--- a/src/tools/clippy/src/docs/float_cmp_const.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for (in-)equality comparisons on floating-point
-value and constant, except in functions called `*eq*` (which probably
-implement equality for a type involving floats).
-
-### Why is this bad?
-Floating point calculations are usually imprecise, so
-asking if two values are *exactly* equal is asking for trouble. For a good
-guide on what to do, see [the floating point
-guide](http://www.floating-point-gui.de/errors/comparison).
-
-### Example
-```
-let x: f64 = 1.0;
-const ONE: f64 = 1.00;
-
-if x == ONE { } // where both are floats
-```
-
-Use instead:
-```
-let error_margin = f64::EPSILON; // Use an epsilon for comparison
-// Or, if Rust <= 1.42, use `std::f64::EPSILON` constant instead.
-// let error_margin = std::f64::EPSILON;
-if (x - ONE).abs() < error_margin { }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/float_equality_without_abs.txt b/src/tools/clippy/src/docs/float_equality_without_abs.txt
deleted file mode 100644
index 556b574e15d..00000000000
--- a/src/tools/clippy/src/docs/float_equality_without_abs.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for statements of the form `(a - b) < f32::EPSILON` or
-`(a - b) < f64::EPSILON`. Notes the missing `.abs()`.
-
-### Why is this bad?
-The code without `.abs()` is more likely to have a bug.
-
-### Known problems
-If the user can ensure that b is larger than a, the `.abs()` is
-technically unnecessary. However, it will make the code more robust and doesn't have any
-large performance implications. If the abs call was deliberately left out for performance
-reasons, it is probably better to state this explicitly in the code, which then can be done
-with an allow.
-
-### Example
-```
-pub fn is_roughly_equal(a: f32, b: f32) -> bool {
-    (a - b) < f32::EPSILON
-}
-```
-Use instead:
-```
-pub fn is_roughly_equal(a: f32, b: f32) -> bool {
-    (a - b).abs() < f32::EPSILON
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/fn_address_comparisons.txt b/src/tools/clippy/src/docs/fn_address_comparisons.txt
deleted file mode 100644
index 7d2b7b681de..00000000000
--- a/src/tools/clippy/src/docs/fn_address_comparisons.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for comparisons with an address of a function item.
-
-### Why is this bad?
-Function item address is not guaranteed to be unique and could vary
-between different code generation units. Furthermore different function items could have
-the same address after being merged together.
-
-### Example
-```
-type F = fn();
-fn a() {}
-let f: F = a;
-if f == a {
-    // ...
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/fn_params_excessive_bools.txt b/src/tools/clippy/src/docs/fn_params_excessive_bools.txt
deleted file mode 100644
index 2eae0563368..00000000000
--- a/src/tools/clippy/src/docs/fn_params_excessive_bools.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-### What it does
-Checks for excessive use of
-bools in function definitions.
-
-### Why is this bad?
-Calls to such functions
-are confusing and error prone, because it's
-hard to remember argument order and you have
-no type system support to back you up. Using
-two-variant enums instead of bools often makes
-API easier to use.
-
-### Example
-```
-fn f(is_round: bool, is_hot: bool) { ... }
-```
-
-Use instead:
-```
-enum Shape {
-    Round,
-    Spiky,
-}
-
-enum Temperature {
-    Hot,
-    IceCold,
-}
-
-fn f(shape: Shape, temperature: Temperature) { ... }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/fn_to_numeric_cast.txt b/src/tools/clippy/src/docs/fn_to_numeric_cast.txt
deleted file mode 100644
index 1f587f6d717..00000000000
--- a/src/tools/clippy/src/docs/fn_to_numeric_cast.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for casts of function pointers to something other than usize
-
-### Why is this bad?
-Casting a function pointer to anything other than usize/isize is not portable across
-architectures, because you end up losing bits if the target type is too small or end up with a
-bunch of extra bits that waste space and add more instructions to the final binary than
-strictly necessary for the problem
-
-Casting to isize also doesn't make sense since there are no signed addresses.
-
-### Example
-```
-fn fun() -> i32 { 1 }
-let _ = fun as i64;
-```
-
-Use instead:
-```
-let _ = fun as usize;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/fn_to_numeric_cast_any.txt b/src/tools/clippy/src/docs/fn_to_numeric_cast_any.txt
deleted file mode 100644
index ee3c33d2372..00000000000
--- a/src/tools/clippy/src/docs/fn_to_numeric_cast_any.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-### What it does
-Checks for casts of a function pointer to any integer type.
-
-### Why is this bad?
-Casting a function pointer to an integer can have surprising results and can occur
-accidentally if parentheses are omitted from a function call. If you aren't doing anything
-low-level with function pointers then you can opt-out of casting functions to integers in
-order to avoid mistakes. Alternatively, you can use this lint to audit all uses of function
-pointer casts in your code.
-
-### Example
-```
-// fn1 is cast as `usize`
-fn fn1() -> u16 {
-    1
-};
-let _ = fn1 as usize;
-```
-
-Use instead:
-```
-// maybe you intended to call the function?
-fn fn2() -> u16 {
-    1
-};
-let _ = fn2() as usize;
-
-// or
-
-// maybe you intended to cast it to a function type?
-fn fn3() -> u16 {
-    1
-}
-let _ = fn3 as fn() -> u16;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/fn_to_numeric_cast_with_truncation.txt b/src/tools/clippy/src/docs/fn_to_numeric_cast_with_truncation.txt
deleted file mode 100644
index 69f12fa319f..00000000000
--- a/src/tools/clippy/src/docs/fn_to_numeric_cast_with_truncation.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for casts of a function pointer to a numeric type not wide enough to
-store address.
-
-### Why is this bad?
-Such a cast discards some bits of the function's address. If this is intended, it would be more
-clearly expressed by casting to usize first, then casting the usize to the intended type (with
-a comment) to perform the truncation.
-
-### Example
-```
-fn fn1() -> i16 {
-    1
-};
-let _ = fn1 as i32;
-```
-
-Use instead:
-```
-// Cast to usize first, then comment with the reason for the truncation
-fn fn1() -> i16 {
-    1
-};
-let fn_ptr = fn1 as usize;
-let fn_ptr_truncated = fn_ptr as i32;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/for_kv_map.txt b/src/tools/clippy/src/docs/for_kv_map.txt
deleted file mode 100644
index a9a2ffee9c7..00000000000
--- a/src/tools/clippy/src/docs/for_kv_map.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for iterating a map (`HashMap` or `BTreeMap`) and
-ignoring either the keys or values.
-
-### Why is this bad?
-Readability. There are `keys` and `values` methods that
-can be used to express that don't need the values or keys.
-
-### Example
-```
-for (k, _) in &map {
-    ..
-}
-```
-
-could be replaced by
-
-```
-for k in map.keys() {
-    ..
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/forget_copy.txt b/src/tools/clippy/src/docs/forget_copy.txt
deleted file mode 100644
index 1d100912e9a..00000000000
--- a/src/tools/clippy/src/docs/forget_copy.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### 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
-```
-let x: i32 = 42; // i32 implements Copy
-std::mem::forget(x) // A copy of x is passed to the function, leaving the
-                    // original unaffected
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/forget_non_drop.txt b/src/tools/clippy/src/docs/forget_non_drop.txt
deleted file mode 100644
index 3307d654c17..00000000000
--- a/src/tools/clippy/src/docs/forget_non_drop.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-### What it does
-Checks for calls to `std::mem::forget` with a value that does not implement `Drop`.
-
-### Why is this bad?
-Calling `std::mem::forget` is no different than dropping such a type. A different value may
-have been intended.
-
-### Example
-```
-struct Foo;
-let x = Foo;
-std::mem::forget(x);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/forget_ref.txt b/src/tools/clippy/src/docs/forget_ref.txt
deleted file mode 100644
index 874fb878606..00000000000
--- a/src/tools/clippy/src/docs/forget_ref.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### 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
-```
-let x = Box::new(1);
-std::mem::forget(&x) // Should have been forget(x), x will still be dropped
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/format_in_format_args.txt b/src/tools/clippy/src/docs/format_in_format_args.txt
deleted file mode 100644
index ac498472f01..00000000000
--- a/src/tools/clippy/src/docs/format_in_format_args.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Detects `format!` within the arguments of another macro that does
-formatting such as `format!` itself, `write!` or `println!`. Suggests
-inlining the `format!` call.
-
-### Why is this bad?
-The recommended code is both shorter and avoids a temporary allocation.
-
-### Example
-```
-println!("error: {}", format!("something failed at {}", Location::caller()));
-```
-Use instead:
-```
-println!("error: something failed at {}", Location::caller());
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/format_push_string.txt b/src/tools/clippy/src/docs/format_push_string.txt
deleted file mode 100644
index ca409ebc7ec..00000000000
--- a/src/tools/clippy/src/docs/format_push_string.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Detects cases where the result of a `format!` call is
-appended to an existing `String`.
-
-### Why is this bad?
-Introduces an extra, avoidable heap allocation.
-
-### Known problems
-`format!` returns a `String` but `write!` returns a `Result`.
-Thus you are forced to ignore the `Err` variant to achieve the same API.
-
-While using `write!` in the suggested way should never fail, this isn't necessarily clear to the programmer.
-
-### Example
-```
-let mut s = String::new();
-s += &format!("0x{:X}", 1024);
-s.push_str(&format!("0x{:X}", 1024));
-```
-Use instead:
-```
-use std::fmt::Write as _; // import without risk of name clashing
-
-let mut s = String::new();
-let _ = write!(s, "0x{:X}", 1024);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/from_iter_instead_of_collect.txt b/src/tools/clippy/src/docs/from_iter_instead_of_collect.txt
deleted file mode 100644
index f3fd2759726..00000000000
--- a/src/tools/clippy/src/docs/from_iter_instead_of_collect.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for `from_iter()` function calls on types that implement the `FromIterator`
-trait.
-
-### Why is this bad?
-It is recommended style to use collect. See
-[FromIterator documentation](https://doc.rust-lang.org/std/iter/trait.FromIterator.html)
-
-### Example
-```
-let five_fives = std::iter::repeat(5).take(5);
-
-let v = Vec::from_iter(five_fives);
-
-assert_eq!(v, vec![5, 5, 5, 5, 5]);
-```
-Use instead:
-```
-let five_fives = std::iter::repeat(5).take(5);
-
-let v: Vec<i32> = five_fives.collect();
-
-assert_eq!(v, vec![5, 5, 5, 5, 5]);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/from_over_into.txt b/src/tools/clippy/src/docs/from_over_into.txt
deleted file mode 100644
index 0770bcc42c2..00000000000
--- a/src/tools/clippy/src/docs/from_over_into.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Searches for implementations of the `Into<..>` trait and suggests to implement `From<..>` instead.
-
-### Why is this bad?
-According the std docs implementing `From<..>` is preferred since it gives you `Into<..>` for free where the reverse isn't true.
-
-### Example
-```
-struct StringWrapper(String);
-
-impl Into<StringWrapper> for String {
-    fn into(self) -> StringWrapper {
-        StringWrapper(self)
-    }
-}
-```
-Use instead:
-```
-struct StringWrapper(String);
-
-impl From<String> for StringWrapper {
-    fn from(s: String) -> StringWrapper {
-        StringWrapper(s)
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/from_str_radix_10.txt b/src/tools/clippy/src/docs/from_str_radix_10.txt
deleted file mode 100644
index f6f319d3eaa..00000000000
--- a/src/tools/clippy/src/docs/from_str_radix_10.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-
-Checks for function invocations of the form `primitive::from_str_radix(s, 10)`
-
-### Why is this bad?
-
-This specific common use case can be rewritten as `s.parse::<primitive>()`
-(and in most cases, the turbofish can be removed), which reduces code length
-and complexity.
-
-### Known problems
-
-This lint may suggest using (&<expression>).parse() instead of <expression>.parse() directly
-in some cases, which is correct but adds unnecessary complexity to the code.
-
-### Example
-```
-let input: &str = get_input();
-let num = u16::from_str_radix(input, 10)?;
-```
-Use instead:
-```
-let input: &str = get_input();
-let num: u16 = input.parse()?;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/future_not_send.txt b/src/tools/clippy/src/docs/future_not_send.txt
deleted file mode 100644
index 0aa048d2735..00000000000
--- a/src/tools/clippy/src/docs/future_not_send.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-This lint requires Future implementations returned from
-functions and methods to implement the `Send` marker trait. It is mostly
-used by library authors (public and internal) that target an audience where
-multithreaded executors are likely to be used for running these Futures.
-
-### Why is this bad?
-A Future implementation captures some state that it
-needs to eventually produce its final value. When targeting a multithreaded
-executor (which is the norm on non-embedded devices) this means that this
-state may need to be transported to other threads, in other words the
-whole Future needs to implement the `Send` marker trait. If it does not,
-then the resulting Future cannot be submitted to a thread pool in the
-end user’s code.
-
-Especially for generic functions it can be confusing to leave the
-discovery of this problem to the end user: the reported error location
-will be far from its cause and can in many cases not even be fixed without
-modifying the library where the offending Future implementation is
-produced.
-
-### Example
-```
-async fn not_send(bytes: std::rc::Rc<[u8]>) {}
-```
-Use instead:
-```
-async fn is_send(bytes: std::sync::Arc<[u8]>) {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/get_first.txt b/src/tools/clippy/src/docs/get_first.txt
deleted file mode 100644
index c905a737ddf..00000000000
--- a/src/tools/clippy/src/docs/get_first.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for using `x.get(0)` instead of
-`x.first()`.
-
-### Why is this bad?
-Using `x.first()` is easier to read and has the same
-result.
-
-### Example
-```
-let x = vec![2, 3, 5];
-let first_element = x.get(0);
-```
-
-Use instead:
-```
-let x = vec![2, 3, 5];
-let first_element = x.first();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/get_last_with_len.txt b/src/tools/clippy/src/docs/get_last_with_len.txt
deleted file mode 100644
index 31c7f269586..00000000000
--- a/src/tools/clippy/src/docs/get_last_with_len.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for using `x.get(x.len() - 1)` instead of
-`x.last()`.
-
-### Why is this bad?
-Using `x.last()` is easier to read and has the same
-result.
-
-Note that using `x[x.len() - 1]` is semantically different from
-`x.last()`.  Indexing into the array will panic on out-of-bounds
-accesses, while `x.get()` and `x.last()` will return `None`.
-
-There is another lint (get_unwrap) that covers the case of using
-`x.get(index).unwrap()` instead of `x[index]`.
-
-### Example
-```
-let x = vec![2, 3, 5];
-let last_element = x.get(x.len() - 1);
-```
-
-Use instead:
-```
-let x = vec![2, 3, 5];
-let last_element = x.last();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/get_unwrap.txt b/src/tools/clippy/src/docs/get_unwrap.txt
deleted file mode 100644
index 8defc222441..00000000000
--- a/src/tools/clippy/src/docs/get_unwrap.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-### What it does
-Checks for use of `.get().unwrap()` (or
-`.get_mut().unwrap`) on a standard library type which implements `Index`
-
-### Why is this bad?
-Using the Index trait (`[]`) is more clear and more
-concise.
-
-### Known problems
-Not a replacement for error handling: Using either
-`.unwrap()` or the Index trait (`[]`) carries the risk of causing a `panic`
-if the value being accessed is `None`. If the use of `.get().unwrap()` is a
-temporary placeholder for dealing with the `Option` type, then this does
-not mitigate the need for error handling. If there is a chance that `.get()`
-will be `None` in your program, then it is advisable that the `None` case
-is handled in a future refactor instead of using `.unwrap()` or the Index
-trait.
-
-### Example
-```
-let mut some_vec = vec![0, 1, 2, 3];
-let last = some_vec.get(3).unwrap();
-*some_vec.get_mut(0).unwrap() = 1;
-```
-The correct use would be:
-```
-let mut some_vec = vec![0, 1, 2, 3];
-let last = some_vec[3];
-some_vec[0] = 1;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/identity_op.txt b/src/tools/clippy/src/docs/identity_op.txt
deleted file mode 100644
index a8e40bb43e9..00000000000
--- a/src/tools/clippy/src/docs/identity_op.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-### What it does
-Checks for identity operations, e.g., `x + 0`.
-
-### Why is this bad?
-This code can be removed without changing the
-meaning. So it just obscures what's going on. Delete it mercilessly.
-
-### Example
-```
-x / 1 + 0 * 1 - 0 | 0;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/if_let_mutex.txt b/src/tools/clippy/src/docs/if_let_mutex.txt
deleted file mode 100644
index 4d873ade9ac..00000000000
--- a/src/tools/clippy/src/docs/if_let_mutex.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Checks for `Mutex::lock` calls in `if let` expression
-with lock calls in any of the else blocks.
-
-### Why is this bad?
-The Mutex lock remains held for the whole
-`if let ... else` block and deadlocks.
-
-### Example
-```
-if let Ok(thing) = mutex.lock() {
-    do_thing();
-} else {
-    mutex.lock();
-}
-```
-Should be written
-```
-let locked = mutex.lock();
-if let Ok(thing) = locked {
-    do_thing(thing);
-} else {
-    use_locked(locked);
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/if_not_else.txt b/src/tools/clippy/src/docs/if_not_else.txt
deleted file mode 100644
index 0e5ac4ce6bb..00000000000
--- a/src/tools/clippy/src/docs/if_not_else.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Checks for usage of `!` or `!=` in an if condition with an
-else branch.
-
-### Why is this bad?
-Negations reduce the readability of statements.
-
-### Example
-```
-if !v.is_empty() {
-    a()
-} else {
-    b()
-}
-```
-
-Could be written:
-
-```
-if v.is_empty() {
-    b()
-} else {
-    a()
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/if_same_then_else.txt b/src/tools/clippy/src/docs/if_same_then_else.txt
deleted file mode 100644
index 75127016bb8..00000000000
--- a/src/tools/clippy/src/docs/if_same_then_else.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for `if/else` with the same body as the *then* part
-and the *else* part.
-
-### Why is this bad?
-This is probably a copy & paste error.
-
-### Example
-```
-let foo = if … {
-    42
-} else {
-    42
-};
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/if_then_some_else_none.txt b/src/tools/clippy/src/docs/if_then_some_else_none.txt
deleted file mode 100644
index 13744f920e3..00000000000
--- a/src/tools/clippy/src/docs/if_then_some_else_none.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for if-else that could be written using either `bool::then` or `bool::then_some`.
-
-### Why is this bad?
-Looks a little redundant. Using `bool::then` is more concise and incurs no loss of clarity.
-For simple calculations and known values, use `bool::then_some`, which is eagerly evaluated
-in comparison to `bool::then`.
-
-### Example
-```
-let a = if v.is_empty() {
-    println!("true!");
-    Some(42)
-} else {
-    None
-};
-```
-
-Could be written:
-
-```
-let a = v.is_empty().then(|| {
-    println!("true!");
-    42
-});
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/ifs_same_cond.txt b/src/tools/clippy/src/docs/ifs_same_cond.txt
deleted file mode 100644
index 024ba5df93a..00000000000
--- a/src/tools/clippy/src/docs/ifs_same_cond.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Checks for consecutive `if`s with the same condition.
-
-### Why is this bad?
-This is probably a copy & paste error.
-
-### Example
-```
-if a == b {
-    …
-} else if a == b {
-    …
-}
-```
-
-Note that this lint ignores all conditions with a function call as it could
-have side effects:
-
-```
-if foo() {
-    …
-} else if foo() { // not linted
-    …
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/implicit_clone.txt b/src/tools/clippy/src/docs/implicit_clone.txt
deleted file mode 100644
index f5aa112c52c..00000000000
--- a/src/tools/clippy/src/docs/implicit_clone.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for the usage of `_.to_owned()`, `vec.to_vec()`, or similar when calling `_.clone()` would be clearer.
-
-### Why is this bad?
-These methods do the same thing as `_.clone()` but may be confusing as
-to why we are calling `to_vec` on something that is already a `Vec` or calling `to_owned` on something that is already owned.
-
-### Example
-```
-let a = vec![1, 2, 3];
-let b = a.to_vec();
-let c = a.to_owned();
-```
-Use instead:
-```
-let a = vec![1, 2, 3];
-let b = a.clone();
-let c = a.clone();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/implicit_hasher.txt b/src/tools/clippy/src/docs/implicit_hasher.txt
deleted file mode 100644
index 0c1f76620f5..00000000000
--- a/src/tools/clippy/src/docs/implicit_hasher.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for public `impl` or `fn` missing generalization
-over different hashers and implicitly defaulting to the default hashing
-algorithm (`SipHash`).
-
-### Why is this bad?
-`HashMap` or `HashSet` with custom hashers cannot be
-used with them.
-
-### Known problems
-Suggestions for replacing constructors can contain
-false-positives. Also applying suggestions can require modification of other
-pieces of code, possibly including external crates.
-
-### Example
-```
-impl<K: Hash + Eq, V> Serialize for HashMap<K, V> { }
-
-pub fn foo(map: &mut HashMap<i32, i32>) { }
-```
-could be rewritten as
-```
-impl<K: Hash + Eq, V, S: BuildHasher> Serialize for HashMap<K, V, S> { }
-
-pub fn foo<S: BuildHasher>(map: &mut HashMap<i32, i32, S>) { }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/implicit_return.txt b/src/tools/clippy/src/docs/implicit_return.txt
deleted file mode 100644
index ee65a636b38..00000000000
--- a/src/tools/clippy/src/docs/implicit_return.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for missing return statements at the end of a block.
-
-### Why is this bad?
-Actually omitting the return keyword is idiomatic Rust code. Programmers
-coming from other languages might prefer the expressiveness of `return`. It's possible to miss
-the last returning statement because the only difference is a missing `;`. Especially in bigger
-code with multiple return paths having a `return` keyword makes it easier to find the
-corresponding statements.
-
-### Example
-```
-fn foo(x: usize) -> usize {
-    x
-}
-```
-add return
-```
-fn foo(x: usize) -> usize {
-    return x;
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/implicit_saturating_add.txt b/src/tools/clippy/src/docs/implicit_saturating_add.txt
deleted file mode 100644
index 5883a5363e2..00000000000
--- a/src/tools/clippy/src/docs/implicit_saturating_add.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for implicit saturating addition.
-
-### Why is this bad?
-The built-in function is more readable and may be faster.
-
-### Example
-```
-let mut u:u32 = 7000;
-
-if u != u32::MAX {
-    u += 1;
-}
-```
-Use instead:
-```
-let mut u:u32 = 7000;
-
-u = u.saturating_add(1);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/implicit_saturating_sub.txt b/src/tools/clippy/src/docs/implicit_saturating_sub.txt
deleted file mode 100644
index 03b47905a21..00000000000
--- a/src/tools/clippy/src/docs/implicit_saturating_sub.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for implicit saturating subtraction.
-
-### Why is this bad?
-Simplicity and readability. Instead we can easily use an builtin function.
-
-### Example
-```
-let mut i: u32 = end - start;
-
-if i != 0 {
-    i -= 1;
-}
-```
-
-Use instead:
-```
-let mut i: u32 = end - start;
-
-i = i.saturating_sub(1);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/imprecise_flops.txt b/src/tools/clippy/src/docs/imprecise_flops.txt
deleted file mode 100644
index e84d81cea98..00000000000
--- a/src/tools/clippy/src/docs/imprecise_flops.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Looks for floating-point expressions that
-can be expressed using built-in methods to improve accuracy
-at the cost of performance.
-
-### Why is this bad?
-Negatively impacts accuracy.
-
-### Example
-```
-let a = 3f32;
-let _ = a.powf(1.0 / 3.0);
-let _ = (1.0 + a).ln();
-let _ = a.exp() - 1.0;
-```
-
-Use instead:
-```
-let a = 3f32;
-let _ = a.cbrt();
-let _ = a.ln_1p();
-let _ = a.exp_m1();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/inconsistent_digit_grouping.txt b/src/tools/clippy/src/docs/inconsistent_digit_grouping.txt
deleted file mode 100644
index aa0b072de1c..00000000000
--- a/src/tools/clippy/src/docs/inconsistent_digit_grouping.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Warns if an integral or floating-point constant is
-grouped inconsistently with underscores.
-
-### Why is this bad?
-Readers may incorrectly interpret inconsistently
-grouped digits.
-
-### Example
-```
-618_64_9189_73_511
-```
-
-Use instead:
-```
-61_864_918_973_511
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/inconsistent_struct_constructor.txt b/src/tools/clippy/src/docs/inconsistent_struct_constructor.txt
deleted file mode 100644
index eb682109a54..00000000000
--- a/src/tools/clippy/src/docs/inconsistent_struct_constructor.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-### What it does
-Checks for struct constructors where all fields are shorthand and
-the order of the field init shorthand in the constructor is inconsistent
-with the order in the struct definition.
-
-### Why is this bad?
-Since the order of fields in a constructor doesn't affect the
-resulted instance as the below example indicates,
-
-```
-#[derive(Debug, PartialEq, Eq)]
-struct Foo {
-    x: i32,
-    y: i32,
-}
-let x = 1;
-let y = 2;
-
-// This assertion never fails:
-assert_eq!(Foo { x, y }, Foo { y, x });
-```
-
-inconsistent order can be confusing and decreases readability and consistency.
-
-### Example
-```
-struct Foo {
-    x: i32,
-    y: i32,
-}
-let x = 1;
-let y = 2;
-
-Foo { y, x };
-```
-
-Use instead:
-```
-Foo { x, y };
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/index_refutable_slice.txt b/src/tools/clippy/src/docs/index_refutable_slice.txt
deleted file mode 100644
index 8a7d52761af..00000000000
--- a/src/tools/clippy/src/docs/index_refutable_slice.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-The lint checks for slice bindings in patterns that are only used to
-access individual slice values.
-
-### Why is this bad?
-Accessing slice values using indices can lead to panics. Using refutable
-patterns can avoid these. Binding to individual values also improves the
-readability as they can be named.
-
-### Limitations
-This lint currently only checks for immutable access inside `if let`
-patterns.
-
-### Example
-```
-let slice: Option<&[u32]> = Some(&[1, 2, 3]);
-
-if let Some(slice) = slice {
-    println!("{}", slice[0]);
-}
-```
-Use instead:
-```
-let slice: Option<&[u32]> = Some(&[1, 2, 3]);
-
-if let Some(&[first, ..]) = slice {
-    println!("{}", first);
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/indexing_slicing.txt b/src/tools/clippy/src/docs/indexing_slicing.txt
deleted file mode 100644
index 76ca6ed318b..00000000000
--- a/src/tools/clippy/src/docs/indexing_slicing.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-### What it does
-Checks for usage of indexing or slicing. Arrays are special cases, this lint
-does report on arrays if we can tell that slicing operations are in bounds and does not
-lint on constant `usize` indexing on arrays because that is handled by rustc's `const_err` lint.
-
-### Why is this bad?
-Indexing and slicing can panic at runtime and there are
-safe alternatives.
-
-### Example
-```
-// Vector
-let x = vec![0; 5];
-
-x[2];
-&x[2..100];
-
-// Array
-let y = [0, 1, 2, 3];
-
-&y[10..100];
-&y[10..];
-```
-
-Use instead:
-```
-
-x.get(2);
-x.get(2..100);
-
-y.get(10);
-y.get(10..100);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/ineffective_bit_mask.txt b/src/tools/clippy/src/docs/ineffective_bit_mask.txt
deleted file mode 100644
index f6e7ef55621..00000000000
--- a/src/tools/clippy/src/docs/ineffective_bit_mask.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Checks for bit masks in comparisons which can be removed
-without changing the outcome. The basic structure can be seen in the
-following table:
-
-|Comparison| Bit Op   |Example     |equals |
-|----------|----------|------------|-------|
-|`>` / `<=`|`\|` / `^`|`x \| 2 > 3`|`x > 3`|
-|`<` / `>=`|`\|` / `^`|`x ^ 1 < 4` |`x < 4`|
-
-### Why is this bad?
-Not equally evil as [`bad_bit_mask`](#bad_bit_mask),
-but still a bit misleading, because the bit mask is ineffective.
-
-### Known problems
-False negatives: This lint will only match instances
-where we have figured out the math (which is for a power-of-two compared
-value). This means things like `x | 1 >= 7` (which would be better written
-as `x >= 6`) will not be reported (but bit masks like this are fairly
-uncommon).
-
-### Example
-```
-if (x | 1 > 3) {  }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/inefficient_to_string.txt b/src/tools/clippy/src/docs/inefficient_to_string.txt
deleted file mode 100644
index f7061d1ce7b..00000000000
--- a/src/tools/clippy/src/docs/inefficient_to_string.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for usage of `.to_string()` on an `&&T` where
-`T` implements `ToString` directly (like `&&str` or `&&String`).
-
-### Why is this bad?
-This bypasses the specialized implementation of
-`ToString` and instead goes through the more expensive string formatting
-facilities.
-
-### Example
-```
-// Generic implementation for `T: Display` is used (slow)
-["foo", "bar"].iter().map(|s| s.to_string());
-
-// OK, the specialized impl is used
-["foo", "bar"].iter().map(|&s| s.to_string());
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/infallible_destructuring_match.txt b/src/tools/clippy/src/docs/infallible_destructuring_match.txt
deleted file mode 100644
index 4b5d3c4ba6c..00000000000
--- a/src/tools/clippy/src/docs/infallible_destructuring_match.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Checks for matches being used to destructure a single-variant enum
-or tuple struct where a `let` will suffice.
-
-### Why is this bad?
-Just readability – `let` doesn't nest, whereas a `match` does.
-
-### Example
-```
-enum Wrapper {
-    Data(i32),
-}
-
-let wrapper = Wrapper::Data(42);
-
-let data = match wrapper {
-    Wrapper::Data(i) => i,
-};
-```
-
-The correct use would be:
-```
-enum Wrapper {
-    Data(i32),
-}
-
-let wrapper = Wrapper::Data(42);
-let Wrapper::Data(data) = wrapper;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/infinite_iter.txt b/src/tools/clippy/src/docs/infinite_iter.txt
deleted file mode 100644
index 8a22fabc549..00000000000
--- a/src/tools/clippy/src/docs/infinite_iter.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-### What it does
-Checks for iteration that is guaranteed to be infinite.
-
-### Why is this bad?
-While there may be places where this is acceptable
-(e.g., in event streams), in most cases this is simply an error.
-
-### Example
-```
-use std::iter;
-
-iter::repeat(1_u8).collect::<Vec<_>>();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/inherent_to_string.txt b/src/tools/clippy/src/docs/inherent_to_string.txt
deleted file mode 100644
index b18e600e9e6..00000000000
--- a/src/tools/clippy/src/docs/inherent_to_string.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Checks for the definition of inherent methods with a signature of `to_string(&self) -> String`.
-
-### Why is this bad?
-This method is also implicitly defined if a type implements the `Display` trait. As the functionality of `Display` is much more versatile, it should be preferred.
-
-### Example
-```
-pub struct A;
-
-impl A {
-    pub fn to_string(&self) -> String {
-        "I am A".to_string()
-    }
-}
-```
-
-Use instead:
-```
-use std::fmt;
-
-pub struct A;
-
-impl fmt::Display for A {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "I am A")
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/inherent_to_string_shadow_display.txt b/src/tools/clippy/src/docs/inherent_to_string_shadow_display.txt
deleted file mode 100644
index a4bd0b622c4..00000000000
--- a/src/tools/clippy/src/docs/inherent_to_string_shadow_display.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-### What it does
-Checks for the definition of inherent methods with a signature of `to_string(&self) -> String` and if the type implementing this method also implements the `Display` trait.
-
-### Why is this bad?
-This method is also implicitly defined if a type implements the `Display` trait. The less versatile inherent method will then shadow the implementation introduced by `Display`.
-
-### Example
-```
-use std::fmt;
-
-pub struct A;
-
-impl A {
-    pub fn to_string(&self) -> String {
-        "I am A".to_string()
-    }
-}
-
-impl fmt::Display for A {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "I am A, too")
-    }
-}
-```
-
-Use instead:
-```
-use std::fmt;
-
-pub struct A;
-
-impl fmt::Display for A {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "I am A")
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/init_numbered_fields.txt b/src/tools/clippy/src/docs/init_numbered_fields.txt
deleted file mode 100644
index ba40af6a5fa..00000000000
--- a/src/tools/clippy/src/docs/init_numbered_fields.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for tuple structs initialized with field syntax.
-It will however not lint if a base initializer is present.
-The lint will also ignore code in macros.
-
-### Why is this bad?
-This may be confusing to the uninitiated and adds no
-benefit as opposed to tuple initializers
-
-### Example
-```
-struct TupleStruct(u8, u16);
-
-let _ = TupleStruct {
-    0: 1,
-    1: 23,
-};
-
-// should be written as
-let base = TupleStruct(1, 23);
-
-// This is OK however
-let _ = TupleStruct { 0: 42, ..base };
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/inline_always.txt b/src/tools/clippy/src/docs/inline_always.txt
deleted file mode 100644
index 7721da4c4cc..00000000000
--- a/src/tools/clippy/src/docs/inline_always.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for items annotated with `#[inline(always)]`,
-unless the annotated function is empty or simply panics.
-
-### Why is this bad?
-While there are valid uses of this annotation (and once
-you know when to use it, by all means `allow` this lint), it's a common
-newbie-mistake to pepper one's code with it.
-
-As a rule of thumb, before slapping `#[inline(always)]` on a function,
-measure if that additional function call really affects your runtime profile
-sufficiently to make up for the increase in compile time.
-
-### Known problems
-False positives, big time. This lint is meant to be
-deactivated by everyone doing serious performance work. This means having
-done the measurement.
-
-### Example
-```
-#[inline(always)]
-fn not_quite_hot_code(..) { ... }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/inline_asm_x86_att_syntax.txt b/src/tools/clippy/src/docs/inline_asm_x86_att_syntax.txt
deleted file mode 100644
index 8eb49d122d8..00000000000
--- a/src/tools/clippy/src/docs/inline_asm_x86_att_syntax.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for usage of AT&T x86 assembly syntax.
-
-### Why is this bad?
-The lint has been enabled to indicate a preference
-for Intel x86 assembly syntax.
-
-### Example
-
-```
-asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax));
-```
-Use instead:
-```
-asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/inline_asm_x86_intel_syntax.txt b/src/tools/clippy/src/docs/inline_asm_x86_intel_syntax.txt
deleted file mode 100644
index 5aa22c8ed23..00000000000
--- a/src/tools/clippy/src/docs/inline_asm_x86_intel_syntax.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for usage of Intel x86 assembly syntax.
-
-### Why is this bad?
-The lint has been enabled to indicate a preference
-for AT&T x86 assembly syntax.
-
-### Example
-
-```
-asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr);
-```
-Use instead:
-```
-asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax));
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/inline_fn_without_body.txt b/src/tools/clippy/src/docs/inline_fn_without_body.txt
deleted file mode 100644
index 127c161aaa2..00000000000
--- a/src/tools/clippy/src/docs/inline_fn_without_body.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Checks for `#[inline]` on trait methods without bodies
-
-### Why is this bad?
-Only implementations of trait methods may be inlined.
-The inline attribute is ignored for trait methods without bodies.
-
-### Example
-```
-trait Animal {
-    #[inline]
-    fn name(&self) -> &'static str;
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/inspect_for_each.txt b/src/tools/clippy/src/docs/inspect_for_each.txt
deleted file mode 100644
index 01a46d6c451..00000000000
--- a/src/tools/clippy/src/docs/inspect_for_each.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for usage of `inspect().for_each()`.
-
-### Why is this bad?
-It is the same as performing the computation
-inside `inspect` at the beginning of the closure in `for_each`.
-
-### Example
-```
-[1,2,3,4,5].iter()
-.inspect(|&x| println!("inspect the number: {}", x))
-.for_each(|&x| {
-    assert!(x >= 0);
-});
-```
-Can be written as
-```
-[1,2,3,4,5].iter()
-.for_each(|&x| {
-    println!("inspect the number: {}", x);
-    assert!(x >= 0);
-});
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/int_plus_one.txt b/src/tools/clippy/src/docs/int_plus_one.txt
deleted file mode 100644
index 1b68f3eeb64..00000000000
--- a/src/tools/clippy/src/docs/int_plus_one.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block
-
-### Why is this bad?
-Readability -- better to use `> y` instead of `>= y + 1`.
-
-### Example
-```
-if x >= y + 1 {}
-```
-
-Use instead:
-```
-if x > y {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/integer_arithmetic.txt b/src/tools/clippy/src/docs/integer_arithmetic.txt
deleted file mode 100644
index ea57a2ef97b..00000000000
--- a/src/tools/clippy/src/docs/integer_arithmetic.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### 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
-```
-a + 1;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/integer_division.txt b/src/tools/clippy/src/docs/integer_division.txt
deleted file mode 100644
index f6d3349810e..00000000000
--- a/src/tools/clippy/src/docs/integer_division.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for division of integers
-
-### Why is this bad?
-When outside of some very specific algorithms,
-integer division is very often a mistake because it discards the
-remainder.
-
-### Example
-```
-let x = 3 / 2;
-println!("{}", x);
-```
-
-Use instead:
-```
-let x = 3f32 / 2f32;
-println!("{}", x);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/into_iter_on_ref.txt b/src/tools/clippy/src/docs/into_iter_on_ref.txt
deleted file mode 100644
index acb6bd474eb..00000000000
--- a/src/tools/clippy/src/docs/into_iter_on_ref.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for `into_iter` calls on references which should be replaced by `iter`
-or `iter_mut`.
-
-### Why is this bad?
-Readability. Calling `into_iter` on a reference will not move out its
-content into the resulting iterator, which is confusing. It is better just call `iter` or
-`iter_mut` directly.
-
-### Example
-```
-(&vec).into_iter();
-```
-
-Use instead:
-```
-(&vec).iter();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/invalid_null_ptr_usage.txt b/src/tools/clippy/src/docs/invalid_null_ptr_usage.txt
deleted file mode 100644
index 6fb3fa3f83d..00000000000
--- a/src/tools/clippy/src/docs/invalid_null_ptr_usage.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-This lint checks for invalid usages of `ptr::null`.
-
-### Why is this bad?
-This causes undefined behavior.
-
-### Example
-```
-// Undefined behavior
-unsafe { std::slice::from_raw_parts(ptr::null(), 0); }
-```
-
-Use instead:
-```
-unsafe { std::slice::from_raw_parts(NonNull::dangling().as_ptr(), 0); }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/invalid_regex.txt b/src/tools/clippy/src/docs/invalid_regex.txt
deleted file mode 100644
index 6c9969b6e1a..00000000000
--- a/src/tools/clippy/src/docs/invalid_regex.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks [regex](https://crates.io/crates/regex) creation
-(with `Regex::new`, `RegexBuilder::new`, or `RegexSet::new`) for correct
-regex syntax.
-
-### Why is this bad?
-This will lead to a runtime panic.
-
-### Example
-```
-Regex::new("(")
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/invalid_upcast_comparisons.txt b/src/tools/clippy/src/docs/invalid_upcast_comparisons.txt
deleted file mode 100644
index 77cb0330803..00000000000
--- a/src/tools/clippy/src/docs/invalid_upcast_comparisons.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for comparisons where the relation is always either
-true or false, but where one side has been upcast so that the comparison is
-necessary. Only integer types are checked.
-
-### Why is this bad?
-An expression like `let x : u8 = ...; (x as u32) > 300`
-will mistakenly imply that it is possible for `x` to be outside the range of
-`u8`.
-
-### Known problems
-https://github.com/rust-lang/rust-clippy/issues/886
-
-### Example
-```
-let x: u8 = 1;
-(x as u32) > 300;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/invalid_utf8_in_unchecked.txt b/src/tools/clippy/src/docs/invalid_utf8_in_unchecked.txt
deleted file mode 100644
index afb5acbe9c5..00000000000
--- a/src/tools/clippy/src/docs/invalid_utf8_in_unchecked.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for `std::str::from_utf8_unchecked` with an invalid UTF-8 literal
-
-### Why is this bad?
-Creating such a `str` would result in undefined behavior
-
-### Example
-```
-unsafe {
-    std::str::from_utf8_unchecked(b"cl\x82ippy");
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/invisible_characters.txt b/src/tools/clippy/src/docs/invisible_characters.txt
deleted file mode 100644
index 3dda380911f..00000000000
--- a/src/tools/clippy/src/docs/invisible_characters.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-### What it does
-Checks for invisible Unicode characters in the code.
-
-### Why is this bad?
-Having an invisible character in the code makes for all
-sorts of April fools, but otherwise is very much frowned upon.
-
-### Example
-You don't see it, but there may be a zero-width space or soft hyphen
-some­where in this text.
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/is_digit_ascii_radix.txt b/src/tools/clippy/src/docs/is_digit_ascii_radix.txt
deleted file mode 100644
index 9f11cf43054..00000000000
--- a/src/tools/clippy/src/docs/is_digit_ascii_radix.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Finds usages of [`char::is_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_digit) that
-can be replaced with [`is_ascii_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_ascii_digit) or
-[`is_ascii_hexdigit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_ascii_hexdigit).
-
-### Why is this bad?
-`is_digit(..)` is slower and requires specifying the radix.
-
-### Example
-```
-let c: char = '6';
-c.is_digit(10);
-c.is_digit(16);
-```
-Use instead:
-```
-let c: char = '6';
-c.is_ascii_digit();
-c.is_ascii_hexdigit();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/items_after_statements.txt b/src/tools/clippy/src/docs/items_after_statements.txt
deleted file mode 100644
index 6fdfff50d20..00000000000
--- a/src/tools/clippy/src/docs/items_after_statements.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-### What it does
-Checks for items declared after some statement in a block.
-
-### Why is this bad?
-Items live for the entire scope they are declared
-in. But statements are processed in order. This might cause confusion as
-it's hard to figure out which item is meant in a statement.
-
-### Example
-```
-fn foo() {
-    println!("cake");
-}
-
-fn main() {
-    foo(); // prints "foo"
-    fn foo() {
-        println!("foo");
-    }
-    foo(); // prints "foo"
-}
-```
-
-Use instead:
-```
-fn foo() {
-    println!("cake");
-}
-
-fn main() {
-    fn foo() {
-        println!("foo");
-    }
-    foo(); // prints "foo"
-    foo(); // prints "foo"
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iter_cloned_collect.txt b/src/tools/clippy/src/docs/iter_cloned_collect.txt
deleted file mode 100644
index 90dc9ebb40f..00000000000
--- a/src/tools/clippy/src/docs/iter_cloned_collect.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for the use of `.cloned().collect()` on slice to
-create a `Vec`.
-
-### Why is this bad?
-`.to_vec()` is clearer
-
-### Example
-```
-let s = [1, 2, 3, 4, 5];
-let s2: Vec<isize> = s[..].iter().cloned().collect();
-```
-The better use would be:
-```
-let s = [1, 2, 3, 4, 5];
-let s2: Vec<isize> = s.to_vec();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iter_count.txt b/src/tools/clippy/src/docs/iter_count.txt
deleted file mode 100644
index f3db4a26c29..00000000000
--- a/src/tools/clippy/src/docs/iter_count.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for the use of `.iter().count()`.
-
-### Why is this bad?
-`.len()` is more efficient and more
-readable.
-
-### Example
-```
-let some_vec = vec![0, 1, 2, 3];
-
-some_vec.iter().count();
-&some_vec[..].iter().count();
-```
-
-Use instead:
-```
-let some_vec = vec![0, 1, 2, 3];
-
-some_vec.len();
-&some_vec[..].len();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iter_kv_map.txt b/src/tools/clippy/src/docs/iter_kv_map.txt
deleted file mode 100644
index a063c8195ef..00000000000
--- a/src/tools/clippy/src/docs/iter_kv_map.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-
-Checks for iterating a map (`HashMap` or `BTreeMap`) and
-ignoring either the keys or values.
-
-### Why is this bad?
-
-Readability. There are `keys` and `values` methods that
-can be used to express that we only need the keys or the values.
-
-### Example
-
-```
-let map: HashMap<u32, u32> = HashMap::new();
-let values = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
-```
-
-Use instead:
-```
-let map: HashMap<u32, u32> = HashMap::new();
-let values = map.values().collect::<Vec<_>>();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iter_next_loop.txt b/src/tools/clippy/src/docs/iter_next_loop.txt
deleted file mode 100644
index b33eb39d6e1..00000000000
--- a/src/tools/clippy/src/docs/iter_next_loop.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for loops on `x.next()`.
-
-### Why is this bad?
-`next()` returns either `Some(value)` if there was a
-value, or `None` otherwise. The insidious thing is that `Option<_>`
-implements `IntoIterator`, so that possibly one value will be iterated,
-leading to some hard to find bugs. No one will want to write such code
-[except to win an Underhanded Rust
-Contest](https://www.reddit.com/r/rust/comments/3hb0wm/underhanded_rust_contest/cu5yuhr).
-
-### Example
-```
-for x in y.next() {
-    ..
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iter_next_slice.txt b/src/tools/clippy/src/docs/iter_next_slice.txt
deleted file mode 100644
index 1cea25eaf30..00000000000
--- a/src/tools/clippy/src/docs/iter_next_slice.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for usage of `iter().next()` on a Slice or an Array
-
-### Why is this bad?
-These can be shortened into `.get()`
-
-### Example
-```
-a[2..].iter().next();
-b.iter().next();
-```
-should be written as:
-```
-a.get(2);
-b.get(0);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iter_not_returning_iterator.txt b/src/tools/clippy/src/docs/iter_not_returning_iterator.txt
deleted file mode 100644
index 0ca862910a6..00000000000
--- a/src/tools/clippy/src/docs/iter_not_returning_iterator.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Detects methods named `iter` or `iter_mut` that do not have a return type that implements `Iterator`.
-
-### Why is this bad?
-Methods named `iter` or `iter_mut` conventionally return an `Iterator`.
-
-### Example
-```
-// `String` does not implement `Iterator`
-struct Data {}
-impl Data {
-    fn iter(&self) -> String {
-        todo!()
-    }
-}
-```
-Use instead:
-```
-use std::str::Chars;
-struct Data {}
-impl Data {
-   fn iter(&self) -> Chars<'static> {
-       todo!()
-   }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iter_nth.txt b/src/tools/clippy/src/docs/iter_nth.txt
deleted file mode 100644
index 3d67d583ffd..00000000000
--- a/src/tools/clippy/src/docs/iter_nth.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for use of `.iter().nth()` (and the related
-`.iter_mut().nth()`) on standard library types with *O*(1) element access.
-
-### Why is this bad?
-`.get()` and `.get_mut()` are more efficient and more
-readable.
-
-### Example
-```
-let some_vec = vec![0, 1, 2, 3];
-let bad_vec = some_vec.iter().nth(3);
-let bad_slice = &some_vec[..].iter().nth(3);
-```
-The correct use would be:
-```
-let some_vec = vec![0, 1, 2, 3];
-let bad_vec = some_vec.get(3);
-let bad_slice = &some_vec[..].get(3);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iter_nth_zero.txt b/src/tools/clippy/src/docs/iter_nth_zero.txt
deleted file mode 100644
index 8efe47a16a1..00000000000
--- a/src/tools/clippy/src/docs/iter_nth_zero.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for the use of `iter.nth(0)`.
-
-### Why is this bad?
-`iter.next()` is equivalent to
-`iter.nth(0)`, as they both consume the next element,
- but is more readable.
-
-### Example
-```
-let x = s.iter().nth(0);
-```
-
-Use instead:
-```
-let x = s.iter().next();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iter_on_empty_collections.txt b/src/tools/clippy/src/docs/iter_on_empty_collections.txt
deleted file mode 100644
index 87c4ec12afa..00000000000
--- a/src/tools/clippy/src/docs/iter_on_empty_collections.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-
-Checks for calls to `iter`, `iter_mut` or `into_iter` on empty collections
-
-### Why is this bad?
-
-It is simpler to use the empty function from the standard library:
-
-### Example
-
-```
-use std::{slice, option};
-let a: slice::Iter<i32> = [].iter();
-let f: option::IntoIter<i32> = None.into_iter();
-```
-Use instead:
-```
-use std::iter;
-let a: iter::Empty<i32> = iter::empty();
-let b: iter::Empty<i32> = iter::empty();
-```
-
-### Known problems
-
-The type of the resulting iterator might become incompatible with its usage
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iter_on_single_items.txt b/src/tools/clippy/src/docs/iter_on_single_items.txt
deleted file mode 100644
index d0388f25d04..00000000000
--- a/src/tools/clippy/src/docs/iter_on_single_items.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-
-Checks for calls to `iter`, `iter_mut` or `into_iter` on collections containing a single item
-
-### Why is this bad?
-
-It is simpler to use the once function from the standard library:
-
-### Example
-
-```
-let a = [123].iter();
-let b = Some(123).into_iter();
-```
-Use instead:
-```
-use std::iter;
-let a = iter::once(&123);
-let b = iter::once(123);
-```
-
-### Known problems
-
-The type of the resulting iterator might become incompatible with its usage
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iter_overeager_cloned.txt b/src/tools/clippy/src/docs/iter_overeager_cloned.txt
deleted file mode 100644
index 2f902a0c2db..00000000000
--- a/src/tools/clippy/src/docs/iter_overeager_cloned.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for usage of `_.cloned().<func>()` where call to `.cloned()` can be postponed.
-
-### Why is this bad?
-It's often inefficient to clone all elements of an iterator, when eventually, only some
-of them will be consumed.
-
-### Known Problems
-This `lint` removes the side of effect of cloning items in the iterator.
-A code that relies on that side-effect could fail.
-
-### Examples
-```
-vec.iter().cloned().take(10);
-vec.iter().cloned().last();
-```
-
-Use instead:
-```
-vec.iter().take(10).cloned();
-vec.iter().last().cloned();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iter_skip_next.txt b/src/tools/clippy/src/docs/iter_skip_next.txt
deleted file mode 100644
index da226b041cf..00000000000
--- a/src/tools/clippy/src/docs/iter_skip_next.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for use of `.skip(x).next()` on iterators.
-
-### Why is this bad?
-`.nth(x)` is cleaner
-
-### Example
-```
-let some_vec = vec![0, 1, 2, 3];
-let bad_vec = some_vec.iter().skip(3).next();
-let bad_slice = &some_vec[..].iter().skip(3).next();
-```
-The correct use would be:
-```
-let some_vec = vec![0, 1, 2, 3];
-let bad_vec = some_vec.iter().nth(3);
-let bad_slice = &some_vec[..].iter().nth(3);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iter_with_drain.txt b/src/tools/clippy/src/docs/iter_with_drain.txt
deleted file mode 100644
index 2c52b99f7a5..00000000000
--- a/src/tools/clippy/src/docs/iter_with_drain.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for use of `.drain(..)` on `Vec` and `VecDeque` for iteration.
-
-### Why is this bad?
-`.into_iter()` is simpler with better performance.
-
-### Example
-```
-let mut foo = vec![0, 1, 2, 3];
-let bar: HashSet<usize> = foo.drain(..).collect();
-```
-Use instead:
-```
-let foo = vec![0, 1, 2, 3];
-let bar: HashSet<usize> = foo.into_iter().collect();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iterator_step_by_zero.txt b/src/tools/clippy/src/docs/iterator_step_by_zero.txt
deleted file mode 100644
index 73ecc99acfc..00000000000
--- a/src/tools/clippy/src/docs/iterator_step_by_zero.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-### What it does
-Checks for calling `.step_by(0)` on iterators which panics.
-
-### Why is this bad?
-This very much looks like an oversight. Use `panic!()` instead if you
-actually intend to panic.
-
-### Example
-```
-for x in (0..100).step_by(0) {
-    //..
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/just_underscores_and_digits.txt b/src/tools/clippy/src/docs/just_underscores_and_digits.txt
deleted file mode 100644
index a8790bcf25b..00000000000
--- a/src/tools/clippy/src/docs/just_underscores_and_digits.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Checks if you have variables whose name consists of just
-underscores and digits.
-
-### Why is this bad?
-It's hard to memorize what a variable means without a
-descriptive name.
-
-### Example
-```
-let _1 = 1;
-let ___1 = 1;
-let __1___2 = 11;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/large_const_arrays.txt b/src/tools/clippy/src/docs/large_const_arrays.txt
deleted file mode 100644
index 71f67854f2a..00000000000
--- a/src/tools/clippy/src/docs/large_const_arrays.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for large `const` arrays that should
-be defined as `static` instead.
-
-### Why is this bad?
-Performance: const variables are inlined upon use.
-Static items result in only one instance and has a fixed location in memory.
-
-### Example
-```
-pub const a = [0u32; 1_000_000];
-```
-
-Use instead:
-```
-pub static a = [0u32; 1_000_000];
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/large_digit_groups.txt b/src/tools/clippy/src/docs/large_digit_groups.txt
deleted file mode 100644
index f60b19345af..00000000000
--- a/src/tools/clippy/src/docs/large_digit_groups.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Warns if the digits of an integral or floating-point
-constant are grouped into groups that
-are too large.
-
-### Why is this bad?
-Negatively impacts readability.
-
-### Example
-```
-let x: u64 = 6186491_8973511;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/large_enum_variant.txt b/src/tools/clippy/src/docs/large_enum_variant.txt
deleted file mode 100644
index 1f95430790d..00000000000
--- a/src/tools/clippy/src/docs/large_enum_variant.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-### What it does
-Checks for large size differences between variants on
-`enum`s.
-
-### Why is this bad?
-Enum size is bounded by the largest variant. Having one
-large variant can penalize the memory layout of that enum.
-
-### Known problems
-This lint obviously cannot take the distribution of
-variants in your running program into account. It is possible that the
-smaller variants make up less than 1% of all instances, in which case
-the overhead is negligible and the boxing is counter-productive. Always
-measure the change this lint suggests.
-
-For types that implement `Copy`, the suggestion to `Box` a variant's
-data would require removing the trait impl. The types can of course
-still be `Clone`, but that is worse ergonomically. Depending on the
-use case it may be possible to store the large data in an auxiliary
-structure (e.g. Arena or ECS).
-
-The lint will ignore the impact of generic types to the type layout by
-assuming every type parameter is zero-sized. Depending on your use case,
-this may lead to a false positive.
-
-### Example
-```
-enum Test {
-    A(i32),
-    B([i32; 8000]),
-}
-```
-
-Use instead:
-```
-// Possibly better
-enum Test2 {
-    A(i32),
-    B(Box<[i32; 8000]>),
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/large_include_file.txt b/src/tools/clippy/src/docs/large_include_file.txt
deleted file mode 100644
index b2a54bd2eb5..00000000000
--- a/src/tools/clippy/src/docs/large_include_file.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for the inclusion of large files via `include_bytes!()`
-and `include_str!()`
-
-### Why is this bad?
-Including large files can increase the size of the binary
-
-### Example
-```
-let included_str = include_str!("very_large_file.txt");
-let included_bytes = include_bytes!("very_large_file.txt");
-```
-
-Use instead:
-```
-use std::fs;
-
-// You can load the file at runtime
-let string = fs::read_to_string("very_large_file.txt")?;
-let bytes = fs::read("very_large_file.txt")?;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/large_stack_arrays.txt b/src/tools/clippy/src/docs/large_stack_arrays.txt
deleted file mode 100644
index 4a6f34785b0..00000000000
--- a/src/tools/clippy/src/docs/large_stack_arrays.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-### What it does
-Checks for local arrays that may be too large.
-
-### Why is this bad?
-Large local arrays may cause stack overflow.
-
-### Example
-```
-let a = [0u32; 1_000_000];
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/large_types_passed_by_value.txt b/src/tools/clippy/src/docs/large_types_passed_by_value.txt
deleted file mode 100644
index bca07f3ac61..00000000000
--- a/src/tools/clippy/src/docs/large_types_passed_by_value.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for functions taking arguments by value, where
-the argument type is `Copy` and large enough to be worth considering
-passing by reference. Does not trigger if the function is being exported,
-because that might induce API breakage, if the parameter is declared as mutable,
-or if the argument is a `self`.
-
-### Why is this bad?
-Arguments passed by value might result in an unnecessary
-shallow copy, taking up more space in the stack and requiring a call to
-`memcpy`, which can be expensive.
-
-### Example
-```
-#[derive(Clone, Copy)]
-struct TooLarge([u8; 2048]);
-
-fn foo(v: TooLarge) {}
-```
-
-Use instead:
-```
-fn foo(v: &TooLarge) {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/len_without_is_empty.txt b/src/tools/clippy/src/docs/len_without_is_empty.txt
deleted file mode 100644
index 47a2e857522..00000000000
--- a/src/tools/clippy/src/docs/len_without_is_empty.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for items that implement `.len()` but not
-`.is_empty()`.
-
-### Why is this bad?
-It is good custom to have both methods, because for
-some data structures, asking about the length will be a costly operation,
-whereas `.is_empty()` can usually answer in constant time. Also it used to
-lead to false positives on the [`len_zero`](#len_zero) lint – currently that
-lint will ignore such entities.
-
-### Example
-```
-impl X {
-    pub fn len(&self) -> usize {
-        ..
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/len_zero.txt b/src/tools/clippy/src/docs/len_zero.txt
deleted file mode 100644
index 664124bd391..00000000000
--- a/src/tools/clippy/src/docs/len_zero.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-### What it does
-Checks for getting the length of something via `.len()`
-just to compare to zero, and suggests using `.is_empty()` where applicable.
-
-### Why is this bad?
-Some structures can answer `.is_empty()` much faster
-than calculating their length. So it is good to get into the habit of using
-`.is_empty()`, and having it is cheap.
-Besides, it makes the intent clearer than a manual comparison in some contexts.
-
-### Example
-```
-if x.len() == 0 {
-    ..
-}
-if y.len() != 0 {
-    ..
-}
-```
-instead use
-```
-if x.is_empty() {
-    ..
-}
-if !y.is_empty() {
-    ..
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/let_and_return.txt b/src/tools/clippy/src/docs/let_and_return.txt
deleted file mode 100644
index eba5a90ddd6..00000000000
--- a/src/tools/clippy/src/docs/let_and_return.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for `let`-bindings, which are subsequently
-returned.
-
-### Why is this bad?
-It is just extraneous code. Remove it to make your code
-more rusty.
-
-### Example
-```
-fn foo() -> String {
-    let x = String::new();
-    x
-}
-```
-instead, use
-```
-fn foo() -> String {
-    String::new()
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/let_underscore_drop.txt b/src/tools/clippy/src/docs/let_underscore_drop.txt
deleted file mode 100644
index 29ce9bf50ce..00000000000
--- a/src/tools/clippy/src/docs/let_underscore_drop.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Checks for `let _ = <expr>`
-where expr has a type that implements `Drop`
-
-### Why is this bad?
-This statement immediately drops the initializer
-expression instead of extending its lifetime to the end of the scope, which
-is often not intended. To extend the expression's lifetime to the end of the
-scope, use an underscore-prefixed name instead (i.e. _var). If you want to
-explicitly drop the expression, `std::mem::drop` conveys your intention
-better and is less error-prone.
-
-### Example
-```
-{
-    let _ = DroppableItem;
-    //                   ^ dropped here
-    /* more code */
-}
-```
-
-Use instead:
-```
-{
-    let _droppable = DroppableItem;
-    /* more code */
-    // dropped at end of scope
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/let_underscore_lock.txt b/src/tools/clippy/src/docs/let_underscore_lock.txt
deleted file mode 100644
index bd8217fb58b..00000000000
--- a/src/tools/clippy/src/docs/let_underscore_lock.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for `let _ = sync_lock`.
-This supports `mutex` and `rwlock` in `std::sync` and `parking_lot`.
-
-### Why is this bad?
-This statement immediately drops the lock instead of
-extending its lifetime to the end of the scope, which is often not intended.
-To extend lock lifetime to the end of the scope, use an underscore-prefixed
-name instead (i.e. _lock). If you want to explicitly drop the lock,
-`std::mem::drop` conveys your intention better and is less error-prone.
-
-### Example
-```
-let _ = mutex.lock();
-```
-
-Use instead:
-```
-let _lock = mutex.lock();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/let_underscore_must_use.txt b/src/tools/clippy/src/docs/let_underscore_must_use.txt
deleted file mode 100644
index 270b81d9a4c..00000000000
--- a/src/tools/clippy/src/docs/let_underscore_must_use.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for `let _ = <expr>` where expr is `#[must_use]`
-
-### Why is this bad?
-It's better to explicitly handle the value of a `#[must_use]`
-expr
-
-### Example
-```
-fn f() -> Result<u32, u32> {
-    Ok(0)
-}
-
-let _ = f();
-// is_ok() is marked #[must_use]
-let _ = f().is_ok();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/let_unit_value.txt b/src/tools/clippy/src/docs/let_unit_value.txt
deleted file mode 100644
index bc16d5b3d81..00000000000
--- a/src/tools/clippy/src/docs/let_unit_value.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-### What it does
-Checks for binding a unit value.
-
-### Why is this bad?
-A unit value cannot usefully be used anywhere. So
-binding one is kind of pointless.
-
-### Example
-```
-let x = {
-    1;
-};
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/linkedlist.txt b/src/tools/clippy/src/docs/linkedlist.txt
deleted file mode 100644
index 986ff1369e3..00000000000
--- a/src/tools/clippy/src/docs/linkedlist.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-### What it does
-Checks for usage of any `LinkedList`, suggesting to use a
-`Vec` or a `VecDeque` (formerly called `RingBuf`).
-
-### Why is this bad?
-Gankro says:
-
-> The TL;DR of `LinkedList` is that it's built on a massive amount of
-pointers and indirection.
-> It wastes memory, it has terrible cache locality, and is all-around slow.
-`RingBuf`, while
-> "only" amortized for push/pop, should be faster in the general case for
-almost every possible
-> workload, and isn't even amortized at all if you can predict the capacity
-you need.
->
-> `LinkedList`s are only really good if you're doing a lot of merging or
-splitting of lists.
-> This is because they can just mangle some pointers instead of actually
-copying the data. Even
-> if you're doing a lot of insertion in the middle of the list, `RingBuf`
-can still be better
-> because of how expensive it is to seek to the middle of a `LinkedList`.
-
-### Known problems
-False positives – the instances where using a
-`LinkedList` makes sense are few and far between, but they can still happen.
-
-### Example
-```
-let x: LinkedList<usize> = LinkedList::new();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/lossy_float_literal.txt b/src/tools/clippy/src/docs/lossy_float_literal.txt
deleted file mode 100644
index bbcb9115ea6..00000000000
--- a/src/tools/clippy/src/docs/lossy_float_literal.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for whole number float literals that
-cannot be represented as the underlying type without loss.
-
-### Why is this bad?
-Rust will silently lose precision during
-conversion to a float.
-
-### Example
-```
-let _: f32 = 16_777_217.0; // 16_777_216.0
-```
-
-Use instead:
-```
-let _: f32 = 16_777_216.0;
-let _: f64 = 16_777_217.0;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/macro_use_imports.txt b/src/tools/clippy/src/docs/macro_use_imports.txt
deleted file mode 100644
index 6a8180a60bc..00000000000
--- a/src/tools/clippy/src/docs/macro_use_imports.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for `#[macro_use] use...`.
-
-### Why is this bad?
-Since the Rust 2018 edition you can import
-macro's directly, this is considered idiomatic.
-
-### Example
-```
-#[macro_use]
-use some_macro;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/main_recursion.txt b/src/tools/clippy/src/docs/main_recursion.txt
deleted file mode 100644
index e49becd15bb..00000000000
--- a/src/tools/clippy/src/docs/main_recursion.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-### What it does
-Checks for recursion using the entrypoint.
-
-### Why is this bad?
-Apart from special setups (which we could detect following attributes like #![no_std]),
-recursing into main() seems like an unintuitive anti-pattern we should be able to detect.
-
-### Example
-```
-fn main() {
-    main();
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_assert.txt b/src/tools/clippy/src/docs/manual_assert.txt
deleted file mode 100644
index 93653081a2c..00000000000
--- a/src/tools/clippy/src/docs/manual_assert.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Detects `if`-then-`panic!` that can be replaced with `assert!`.
-
-### Why is this bad?
-`assert!` is simpler than `if`-then-`panic!`.
-
-### Example
-```
-let sad_people: Vec<&str> = vec![];
-if !sad_people.is_empty() {
-    panic!("there are sad people: {:?}", sad_people);
-}
-```
-Use instead:
-```
-let sad_people: Vec<&str> = vec![];
-assert!(sad_people.is_empty(), "there are sad people: {:?}", sad_people);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_async_fn.txt b/src/tools/clippy/src/docs/manual_async_fn.txt
deleted file mode 100644
index d01ac402e0d..00000000000
--- a/src/tools/clippy/src/docs/manual_async_fn.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-It checks for manual implementations of `async` functions.
-
-### Why is this bad?
-It's more idiomatic to use the dedicated syntax.
-
-### Example
-```
-use std::future::Future;
-
-fn foo() -> impl Future<Output = i32> { async { 42 } }
-```
-Use instead:
-```
-async fn foo() -> i32 { 42 }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_bits.txt b/src/tools/clippy/src/docs/manual_bits.txt
deleted file mode 100644
index b96c2eb151d..00000000000
--- a/src/tools/clippy/src/docs/manual_bits.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for uses of `std::mem::size_of::<T>() * 8` when
-`T::BITS` is available.
-
-### Why is this bad?
-Can be written as the shorter `T::BITS`.
-
-### Example
-```
-std::mem::size_of::<usize>() * 8;
-```
-Use instead:
-```
-usize::BITS as usize;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_clamp.txt b/src/tools/clippy/src/docs/manual_clamp.txt
deleted file mode 100644
index 8993f6683ad..00000000000
--- a/src/tools/clippy/src/docs/manual_clamp.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-### What it does
-Identifies good opportunities for a clamp function from std or core, and suggests using it.
-
-### Why is this bad?
-clamp is much shorter, easier to read, and doesn't use any control flow.
-
-### Known issue(s)
-If the clamped variable is NaN this suggestion will cause the code to propagate NaN
-rather than returning either `max` or `min`.
-
-`clamp` functions will panic if `max < min`, `max.is_nan()`, or `min.is_nan()`.
-Some may consider panicking in these situations to be desirable, but it also may
-introduce panicking where there wasn't any before.
-
-### Examples
-```
-if input > max {
-    max
-} else if input < min {
-    min
-} else {
-    input
-}
-```
-
-```
-input.max(min).min(max)
-```
-
-```
-match input {
-    x if x > max => max,
-    x if x < min => min,
-    x => x,
-}
-```
-
-```
-let mut x = input;
-if x < min { x = min; }
-if x > max { x = max; }
-```
-Use instead:
-```
-input.clamp(min, max)
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_filter.txt b/src/tools/clippy/src/docs/manual_filter.txt
deleted file mode 100644
index 19a4d9319d9..00000000000
--- a/src/tools/clippy/src/docs/manual_filter.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for usages of `match` which could be implemented using `filter`
-
-### Why is this bad?
-Using the `filter` method is clearer and more concise.
-
-### Example
-```
-match Some(0) {
-    Some(x) => if x % 2 == 0 {
-                    Some(x)
-               } else {
-                    None
-                },
-    None => None,
-};
-```
-Use instead:
-```
-Some(0).filter(|&x| x % 2 == 0);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_filter_map.txt b/src/tools/clippy/src/docs/manual_filter_map.txt
deleted file mode 100644
index 3b6860798ff..00000000000
--- a/src/tools/clippy/src/docs/manual_filter_map.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for usage of `_.filter(_).map(_)` that can be written more simply
-as `filter_map(_)`.
-
-### Why is this bad?
-Redundant code in the `filter` and `map` operations is poor style and
-less performant.
-
-### Example
-```
-(0_i32..10)
-    .filter(|n| n.checked_add(1).is_some())
-    .map(|n| n.checked_add(1).unwrap());
-```
-
-Use instead:
-```
-(0_i32..10).filter_map(|n| n.checked_add(1));
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_find.txt b/src/tools/clippy/src/docs/manual_find.txt
deleted file mode 100644
index e3e07a2771f..00000000000
--- a/src/tools/clippy/src/docs/manual_find.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Check for manual implementations of Iterator::find
-
-### Why is this bad?
-It doesn't affect performance, but using `find` is shorter and easier to read.
-
-### Example
-
-```
-fn example(arr: Vec<i32>) -> Option<i32> {
-    for el in arr {
-        if el == 1 {
-            return Some(el);
-        }
-    }
-    None
-}
-```
-Use instead:
-```
-fn example(arr: Vec<i32>) -> Option<i32> {
-    arr.into_iter().find(|&el| el == 1)
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_find_map.txt b/src/tools/clippy/src/docs/manual_find_map.txt
deleted file mode 100644
index 83b22060c0e..00000000000
--- a/src/tools/clippy/src/docs/manual_find_map.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for usage of `_.find(_).map(_)` that can be written more simply
-as `find_map(_)`.
-
-### Why is this bad?
-Redundant code in the `find` and `map` operations is poor style and
-less performant.
-
-### Example
-```
-(0_i32..10)
-    .find(|n| n.checked_add(1).is_some())
-    .map(|n| n.checked_add(1).unwrap());
-```
-
-Use instead:
-```
-(0_i32..10).find_map(|n| n.checked_add(1));
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_flatten.txt b/src/tools/clippy/src/docs/manual_flatten.txt
deleted file mode 100644
index 62d5f3ec935..00000000000
--- a/src/tools/clippy/src/docs/manual_flatten.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Check for unnecessary `if let` usage in a for loop
-where only the `Some` or `Ok` variant of the iterator element is used.
-
-### Why is this bad?
-It is verbose and can be simplified
-by first calling the `flatten` method on the `Iterator`.
-
-### Example
-
-```
-let x = vec![Some(1), Some(2), Some(3)];
-for n in x {
-    if let Some(n) = n {
-        println!("{}", n);
-    }
-}
-```
-Use instead:
-```
-let x = vec![Some(1), Some(2), Some(3)];
-for n in x.into_iter().flatten() {
-    println!("{}", n);
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_instant_elapsed.txt b/src/tools/clippy/src/docs/manual_instant_elapsed.txt
deleted file mode 100644
index dde3d493c70..00000000000
--- a/src/tools/clippy/src/docs/manual_instant_elapsed.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Lints subtraction between `Instant::now()` and another `Instant`.
-
-### Why is this bad?
-It is easy to accidentally write `prev_instant - Instant::now()`, which will always be 0ns
-as `Instant` subtraction saturates.
-
-`prev_instant.elapsed()` also more clearly signals intention.
-
-### Example
-```
-use std::time::Instant;
-let prev_instant = Instant::now();
-let duration = Instant::now() - prev_instant;
-```
-Use instead:
-```
-use std::time::Instant;
-let prev_instant = Instant::now();
-let duration = prev_instant.elapsed();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_map.txt b/src/tools/clippy/src/docs/manual_map.txt
deleted file mode 100644
index 7f68ccd1037..00000000000
--- a/src/tools/clippy/src/docs/manual_map.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for usages of `match` which could be implemented using `map`
-
-### Why is this bad?
-Using the `map` method is clearer and more concise.
-
-### Example
-```
-match Some(0) {
-    Some(x) => Some(x + 1),
-    None => None,
-};
-```
-Use instead:
-```
-Some(0).map(|x| x + 1);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_memcpy.txt b/src/tools/clippy/src/docs/manual_memcpy.txt
deleted file mode 100644
index d7690bf2586..00000000000
--- a/src/tools/clippy/src/docs/manual_memcpy.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for for-loops that manually copy items between
-slices that could be optimized by having a memcpy.
-
-### Why is this bad?
-It is not as fast as a memcpy.
-
-### Example
-```
-for i in 0..src.len() {
-    dst[i + 64] = src[i];
-}
-```
-
-Use instead:
-```
-dst[64..(src.len() + 64)].clone_from_slice(&src[..]);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_non_exhaustive.txt b/src/tools/clippy/src/docs/manual_non_exhaustive.txt
deleted file mode 100644
index fb021393bd7..00000000000
--- a/src/tools/clippy/src/docs/manual_non_exhaustive.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-### What it does
-Checks for manual implementations of the non-exhaustive pattern.
-
-### Why is this bad?
-Using the #[non_exhaustive] attribute expresses better the intent
-and allows possible optimizations when applied to enums.
-
-### Example
-```
-struct S {
-    pub a: i32,
-    pub b: i32,
-    _c: (),
-}
-
-enum E {
-    A,
-    B,
-    #[doc(hidden)]
-    _C,
-}
-
-struct T(pub i32, pub i32, ());
-```
-Use instead:
-```
-#[non_exhaustive]
-struct S {
-    pub a: i32,
-    pub b: i32,
-}
-
-#[non_exhaustive]
-enum E {
-    A,
-    B,
-}
-
-#[non_exhaustive]
-struct T(pub i32, pub i32);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_ok_or.txt b/src/tools/clippy/src/docs/manual_ok_or.txt
deleted file mode 100644
index 5accdf25965..00000000000
--- a/src/tools/clippy/src/docs/manual_ok_or.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-
-Finds patterns that reimplement `Option::ok_or`.
-
-### Why is this bad?
-
-Concise code helps focusing on behavior instead of boilerplate.
-
-### Examples
-```
-let foo: Option<i32> = None;
-foo.map_or(Err("error"), |v| Ok(v));
-```
-
-Use instead:
-```
-let foo: Option<i32> = None;
-foo.ok_or("error");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_range_contains.txt b/src/tools/clippy/src/docs/manual_range_contains.txt
deleted file mode 100644
index 0ade26951d3..00000000000
--- a/src/tools/clippy/src/docs/manual_range_contains.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for expressions like `x >= 3 && x < 8` that could
-be more readably expressed as `(3..8).contains(x)`.
-
-### Why is this bad?
-`contains` expresses the intent better and has less
-failure modes (such as fencepost errors or using `||` instead of `&&`).
-
-### Example
-```
-// given
-let x = 6;
-
-assert!(x >= 3 && x < 8);
-```
-Use instead:
-```
-assert!((3..8).contains(&x));
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_rem_euclid.txt b/src/tools/clippy/src/docs/manual_rem_euclid.txt
deleted file mode 100644
index d3bb8c61304..00000000000
--- a/src/tools/clippy/src/docs/manual_rem_euclid.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for an expression like `((x % 4) + 4) % 4` which is a common manual reimplementation
-of `x.rem_euclid(4)`.
-
-### Why is this bad?
-It's simpler and more readable.
-
-### Example
-```
-let x: i32 = 24;
-let rem = ((x % 4) + 4) % 4;
-```
-Use instead:
-```
-let x: i32 = 24;
-let rem = x.rem_euclid(4);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_retain.txt b/src/tools/clippy/src/docs/manual_retain.txt
deleted file mode 100644
index cd4f65a93fc..00000000000
--- a/src/tools/clippy/src/docs/manual_retain.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for code to be replaced by `.retain()`.
-### Why is this bad?
-`.retain()` is simpler and avoids needless allocation.
-### Example
-```
-let mut vec = vec![0, 1, 2];
-vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect();
-vec = vec.into_iter().filter(|x| x % 2 == 0).collect();
-```
-Use instead:
-```
-let mut vec = vec![0, 1, 2];
-vec.retain(|x| x % 2 == 0);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_saturating_arithmetic.txt b/src/tools/clippy/src/docs/manual_saturating_arithmetic.txt
deleted file mode 100644
index d9f5d3d1187..00000000000
--- a/src/tools/clippy/src/docs/manual_saturating_arithmetic.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for `.checked_add/sub(x).unwrap_or(MAX/MIN)`.
-
-### Why is this bad?
-These can be written simply with `saturating_add/sub` methods.
-
-### Example
-```
-let add = x.checked_add(y).unwrap_or(u32::MAX);
-let sub = x.checked_sub(y).unwrap_or(u32::MIN);
-```
-
-can be written using dedicated methods for saturating addition/subtraction as:
-
-```
-let add = x.saturating_add(y);
-let sub = x.saturating_sub(y);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_split_once.txt b/src/tools/clippy/src/docs/manual_split_once.txt
deleted file mode 100644
index 291ae447de0..00000000000
--- a/src/tools/clippy/src/docs/manual_split_once.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Checks for usages of `str::splitn(2, _)`
-
-### Why is this bad?
-`split_once` is both clearer in intent and slightly more efficient.
-
-### Example
-```
-let s = "key=value=add";
-let (key, value) = s.splitn(2, '=').next_tuple()?;
-let value = s.splitn(2, '=').nth(1)?;
-
-let mut parts = s.splitn(2, '=');
-let key = parts.next()?;
-let value = parts.next()?;
-```
-
-Use instead:
-```
-let s = "key=value=add";
-let (key, value) = s.split_once('=')?;
-let value = s.split_once('=')?.1;
-
-let (key, value) = s.split_once('=')?;
-```
-
-### Limitations
-The multiple statement variant currently only detects `iter.next()?`/`iter.next().unwrap()`
-in two separate `let` statements that immediately follow the `splitn()`
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_str_repeat.txt b/src/tools/clippy/src/docs/manual_str_repeat.txt
deleted file mode 100644
index 1d4a7a48e20..00000000000
--- a/src/tools/clippy/src/docs/manual_str_repeat.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for manual implementations of `str::repeat`
-
-### Why is this bad?
-These are both harder to read, as well as less performant.
-
-### Example
-```
-let x: String = std::iter::repeat('x').take(10).collect();
-```
-
-Use instead:
-```
-let x: String = "x".repeat(10);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_string_new.txt b/src/tools/clippy/src/docs/manual_string_new.txt
deleted file mode 100644
index 4cbc43f8f84..00000000000
--- a/src/tools/clippy/src/docs/manual_string_new.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-
-Checks for usage of `""` to create a `String`, such as `"".to_string()`, `"".to_owned()`,
-`String::from("")` and others.
-
-### Why is this bad?
-
-Different ways of creating an empty string makes your code less standardized, which can
-be confusing.
-
-### Example
-```
-let a = "".to_string();
-let b: String = "".into();
-```
-Use instead:
-```
-let a = String::new();
-let b = String::new();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_strip.txt b/src/tools/clippy/src/docs/manual_strip.txt
deleted file mode 100644
index f32d8e7a09b..00000000000
--- a/src/tools/clippy/src/docs/manual_strip.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing using
-the pattern's length.
-
-### Why is this bad?
-Using `str:strip_{prefix,suffix}` is safer and may have better performance as there is no
-slicing which may panic and the compiler does not need to insert this panic code. It is
-also sometimes more readable as it removes the need for duplicating or storing the pattern
-used by `str::{starts,ends}_with` and in the slicing.
-
-### Example
-```
-let s = "hello, world!";
-if s.starts_with("hello, ") {
-    assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
-}
-```
-Use instead:
-```
-let s = "hello, world!";
-if let Some(end) = s.strip_prefix("hello, ") {
-    assert_eq!(end.to_uppercase(), "WORLD!");
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_swap.txt b/src/tools/clippy/src/docs/manual_swap.txt
deleted file mode 100644
index bd9526288e3..00000000000
--- a/src/tools/clippy/src/docs/manual_swap.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for manual swapping.
-
-### Why is this bad?
-The `std::mem::swap` function exposes the intent better
-without deinitializing or copying either variable.
-
-### Example
-```
-let mut a = 42;
-let mut b = 1337;
-
-let t = b;
-b = a;
-a = t;
-```
-Use std::mem::swap():
-```
-let mut a = 1;
-let mut b = 2;
-std::mem::swap(&mut a, &mut b);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_unwrap_or.txt b/src/tools/clippy/src/docs/manual_unwrap_or.txt
deleted file mode 100644
index 1fd7d831bfc..00000000000
--- a/src/tools/clippy/src/docs/manual_unwrap_or.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Finds patterns that reimplement `Option::unwrap_or` or `Result::unwrap_or`.
-
-### Why is this bad?
-Concise code helps focusing on behavior instead of boilerplate.
-
-### Example
-```
-let foo: Option<i32> = None;
-match foo {
-    Some(v) => v,
-    None => 1,
-};
-```
-
-Use instead:
-```
-let foo: Option<i32> = None;
-foo.unwrap_or(1);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/many_single_char_names.txt b/src/tools/clippy/src/docs/many_single_char_names.txt
deleted file mode 100644
index 55ee5da5557..00000000000
--- a/src/tools/clippy/src/docs/many_single_char_names.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for too many variables whose name consists of a
-single character.
-
-### Why is this bad?
-It's hard to memorize what a variable means without a
-descriptive name.
-
-### Example
-```
-let (a, b, c, d, e, f, g) = (...);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/map_clone.txt b/src/tools/clippy/src/docs/map_clone.txt
deleted file mode 100644
index 3ee27f072ef..00000000000
--- a/src/tools/clippy/src/docs/map_clone.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for usage of `map(|x| x.clone())` or
-dereferencing closures for `Copy` types, on `Iterator` or `Option`,
-and suggests `cloned()` or `copied()` instead
-
-### Why is this bad?
-Readability, this can be written more concisely
-
-### Example
-```
-let x = vec![42, 43];
-let y = x.iter();
-let z = y.map(|i| *i);
-```
-
-The correct use would be:
-
-```
-let x = vec![42, 43];
-let y = x.iter();
-let z = y.cloned();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/map_collect_result_unit.txt b/src/tools/clippy/src/docs/map_collect_result_unit.txt
deleted file mode 100644
index 9b720612495..00000000000
--- a/src/tools/clippy/src/docs/map_collect_result_unit.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Checks for usage of `_.map(_).collect::<Result<(), _>()`.
-
-### Why is this bad?
-Using `try_for_each` instead is more readable and idiomatic.
-
-### Example
-```
-(0..3).map(|t| Err(t)).collect::<Result<(), _>>();
-```
-Use instead:
-```
-(0..3).try_for_each(|t| Err(t));
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/map_entry.txt b/src/tools/clippy/src/docs/map_entry.txt
deleted file mode 100644
index 20dba1798d0..00000000000
--- a/src/tools/clippy/src/docs/map_entry.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-### What it does
-Checks for uses of `contains_key` + `insert` on `HashMap`
-or `BTreeMap`.
-
-### Why is this bad?
-Using `entry` is more efficient.
-
-### Known problems
-The suggestion may have type inference errors in some cases. e.g.
-```
-let mut map = std::collections::HashMap::new();
-let _ = if !map.contains_key(&0) {
-    map.insert(0, 0)
-} else {
-    None
-};
-```
-
-### Example
-```
-if !map.contains_key(&k) {
-    map.insert(k, v);
-}
-```
-Use instead:
-```
-map.entry(k).or_insert(v);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/map_err_ignore.txt b/src/tools/clippy/src/docs/map_err_ignore.txt
deleted file mode 100644
index 2606c13a7af..00000000000
--- a/src/tools/clippy/src/docs/map_err_ignore.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-### What it does
-Checks for instances of `map_err(|_| Some::Enum)`
-
-### Why is this bad?
-This `map_err` throws away the original error rather than allowing the enum to contain and report the cause of the error
-
-### Example
-Before:
-```
-use std::fmt;
-
-#[derive(Debug)]
-enum Error {
-    Indivisible,
-    Remainder(u8),
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Error::Indivisible => write!(f, "could not divide input by three"),
-            Error::Remainder(remainder) => write!(
-                f,
-                "input is not divisible by three, remainder = {}",
-                remainder
-            ),
-        }
-    }
-}
-
-impl std::error::Error for Error {}
-
-fn divisible_by_3(input: &str) -> Result<(), Error> {
-    input
-        .parse::<i32>()
-        .map_err(|_| Error::Indivisible)
-        .map(|v| v % 3)
-        .and_then(|remainder| {
-            if remainder == 0 {
-                Ok(())
-            } else {
-                Err(Error::Remainder(remainder as u8))
-            }
-        })
-}
- ```
-
- After:
- ```rust
-use std::{fmt, num::ParseIntError};
-
-#[derive(Debug)]
-enum Error {
-    Indivisible(ParseIntError),
-    Remainder(u8),
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Error::Indivisible(_) => write!(f, "could not divide input by three"),
-            Error::Remainder(remainder) => write!(
-                f,
-                "input is not divisible by three, remainder = {}",
-                remainder
-            ),
-        }
-    }
-}
-
-impl std::error::Error for Error {
-    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
-        match self {
-            Error::Indivisible(source) => Some(source),
-            _ => None,
-        }
-    }
-}
-
-fn divisible_by_3(input: &str) -> Result<(), Error> {
-    input
-        .parse::<i32>()
-        .map_err(Error::Indivisible)
-        .map(|v| v % 3)
-        .and_then(|remainder| {
-            if remainder == 0 {
-                Ok(())
-            } else {
-                Err(Error::Remainder(remainder as u8))
-            }
-        })
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/map_flatten.txt b/src/tools/clippy/src/docs/map_flatten.txt
deleted file mode 100644
index 73c0e51407f..00000000000
--- a/src/tools/clippy/src/docs/map_flatten.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for usage of `_.map(_).flatten(_)` on `Iterator` and `Option`
-
-### Why is this bad?
-Readability, this can be written more concisely as
-`_.flat_map(_)` for `Iterator` or `_.and_then(_)` for `Option`
-
-### Example
-```
-let vec = vec![vec![1]];
-let opt = Some(5);
-
-vec.iter().map(|x| x.iter()).flatten();
-opt.map(|x| Some(x * 2)).flatten();
-```
-
-Use instead:
-```
-vec.iter().flat_map(|x| x.iter());
-opt.and_then(|x| Some(x * 2));
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/map_identity.txt b/src/tools/clippy/src/docs/map_identity.txt
deleted file mode 100644
index e2e7af0bed9..00000000000
--- a/src/tools/clippy/src/docs/map_identity.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for instances of `map(f)` where `f` is the identity function.
-
-### Why is this bad?
-It can be written more concisely without the call to `map`.
-
-### Example
-```
-let x = [1, 2, 3];
-let y: Vec<_> = x.iter().map(|x| x).map(|x| 2*x).collect();
-```
-Use instead:
-```
-let x = [1, 2, 3];
-let y: Vec<_> = x.iter().map(|x| 2*x).collect();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/map_unwrap_or.txt b/src/tools/clippy/src/docs/map_unwrap_or.txt
deleted file mode 100644
index 485b29f01b1..00000000000
--- a/src/tools/clippy/src/docs/map_unwrap_or.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for usage of `option.map(_).unwrap_or(_)` or `option.map(_).unwrap_or_else(_)` or
-`result.map(_).unwrap_or_else(_)`.
-
-### Why is this bad?
-Readability, these can be written more concisely (resp.) as
-`option.map_or(_, _)`, `option.map_or_else(_, _)` and `result.map_or_else(_, _)`.
-
-### Known problems
-The order of the arguments is not in execution order
-
-### Examples
-```
-option.map(|a| a + 1).unwrap_or(0);
-result.map(|a| a + 1).unwrap_or_else(some_function);
-```
-
-Use instead:
-```
-option.map_or(0, |a| a + 1);
-result.map_or_else(some_function, |a| a + 1);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/match_as_ref.txt b/src/tools/clippy/src/docs/match_as_ref.txt
deleted file mode 100644
index 5e5f3d645a4..00000000000
--- a/src/tools/clippy/src/docs/match_as_ref.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for match which is used to add a reference to an
-`Option` value.
-
-### Why is this bad?
-Using `as_ref()` or `as_mut()` instead is shorter.
-
-### Example
-```
-let x: Option<()> = None;
-
-let r: Option<&()> = match x {
-    None => None,
-    Some(ref v) => Some(v),
-};
-```
-
-Use instead:
-```
-let x: Option<()> = None;
-
-let r: Option<&()> = x.as_ref();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/match_bool.txt b/src/tools/clippy/src/docs/match_bool.txt
deleted file mode 100644
index 96f9e1f8b7d..00000000000
--- a/src/tools/clippy/src/docs/match_bool.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for matches where match expression is a `bool`. It
-suggests to replace the expression with an `if...else` block.
-
-### Why is this bad?
-It makes the code less readable.
-
-### Example
-```
-let condition: bool = true;
-match condition {
-    true => foo(),
-    false => bar(),
-}
-```
-Use if/else instead:
-```
-let condition: bool = true;
-if condition {
-    foo();
-} else {
-    bar();
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/match_like_matches_macro.txt b/src/tools/clippy/src/docs/match_like_matches_macro.txt
deleted file mode 100644
index 643e2ddc97b..00000000000
--- a/src/tools/clippy/src/docs/match_like_matches_macro.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-### What it does
-Checks for `match`  or `if let` expressions producing a
-`bool` that could be written using `matches!`
-
-### Why is this bad?
-Readability and needless complexity.
-
-### Known problems
-This lint falsely triggers, if there are arms with
-`cfg` attributes that remove an arm evaluating to `false`.
-
-### Example
-```
-let x = Some(5);
-
-let a = match x {
-    Some(0) => true,
-    _ => false,
-};
-
-let a = if let Some(0) = x {
-    true
-} else {
-    false
-};
-```
-
-Use instead:
-```
-let x = Some(5);
-let a = matches!(x, Some(0));
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/match_on_vec_items.txt b/src/tools/clippy/src/docs/match_on_vec_items.txt
deleted file mode 100644
index 981d18d0f9e..00000000000
--- a/src/tools/clippy/src/docs/match_on_vec_items.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Checks for `match vec[idx]` or `match vec[n..m]`.
-
-### Why is this bad?
-This can panic at runtime.
-
-### Example
-```
-let arr = vec![0, 1, 2, 3];
-let idx = 1;
-
-match arr[idx] {
-    0 => println!("{}", 0),
-    1 => println!("{}", 3),
-    _ => {},
-}
-```
-
-Use instead:
-```
-let arr = vec![0, 1, 2, 3];
-let idx = 1;
-
-match arr.get(idx) {
-    Some(0) => println!("{}", 0),
-    Some(1) => println!("{}", 3),
-    _ => {},
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/match_overlapping_arm.txt b/src/tools/clippy/src/docs/match_overlapping_arm.txt
deleted file mode 100644
index 841c091bd5c..00000000000
--- a/src/tools/clippy/src/docs/match_overlapping_arm.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for overlapping match arms.
-
-### Why is this bad?
-It is likely to be an error and if not, makes the code
-less obvious.
-
-### Example
-```
-let x = 5;
-match x {
-    1..=10 => println!("1 ... 10"),
-    5..=15 => println!("5 ... 15"),
-    _ => (),
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/match_ref_pats.txt b/src/tools/clippy/src/docs/match_ref_pats.txt
deleted file mode 100644
index b1d90299509..00000000000
--- a/src/tools/clippy/src/docs/match_ref_pats.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for matches where all arms match a reference,
-suggesting to remove the reference and deref the matched expression
-instead. It also checks for `if let &foo = bar` blocks.
-
-### Why is this bad?
-It just makes the code less readable. That reference
-destructuring adds nothing to the code.
-
-### Example
-```
-match x {
-    &A(ref y) => foo(y),
-    &B => bar(),
-    _ => frob(&x),
-}
-```
-
-Use instead:
-```
-match *x {
-    A(ref y) => foo(y),
-    B => bar(),
-    _ => frob(x),
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/match_result_ok.txt b/src/tools/clippy/src/docs/match_result_ok.txt
deleted file mode 100644
index eea7c8e00f1..00000000000
--- a/src/tools/clippy/src/docs/match_result_ok.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for unnecessary `ok()` in `while let`.
-
-### Why is this bad?
-Calling `ok()` in `while let` is unnecessary, instead match
-on `Ok(pat)`
-
-### Example
-```
-while let Some(value) = iter.next().ok() {
-    vec.push(value)
-}
-
-if let Some(value) = iter.next().ok() {
-    vec.push(value)
-}
-```
-Use instead:
-```
-while let Ok(value) = iter.next() {
-    vec.push(value)
-}
-
-if let Ok(value) = iter.next() {
-       vec.push(value)
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/match_same_arms.txt b/src/tools/clippy/src/docs/match_same_arms.txt
deleted file mode 100644
index 14edf12032e..00000000000
--- a/src/tools/clippy/src/docs/match_same_arms.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-### What it does
-Checks for `match` with identical arm bodies.
-
-### Why is this bad?
-This is probably a copy & paste error. If arm bodies
-are the same on purpose, you can factor them
-[using `|`](https://doc.rust-lang.org/book/patterns.html#multiple-patterns).
-
-### Known problems
-False positive possible with order dependent `match`
-(see issue
-[#860](https://github.com/rust-lang/rust-clippy/issues/860)).
-
-### Example
-```
-match foo {
-    Bar => bar(),
-    Quz => quz(),
-    Baz => bar(), // <= oops
-}
-```
-
-This should probably be
-```
-match foo {
-    Bar => bar(),
-    Quz => quz(),
-    Baz => baz(), // <= fixed
-}
-```
-
-or if the original code was not a typo:
-```
-match foo {
-    Bar | Baz => bar(), // <= shows the intent better
-    Quz => quz(),
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/match_single_binding.txt b/src/tools/clippy/src/docs/match_single_binding.txt
deleted file mode 100644
index 67ded0bbd55..00000000000
--- a/src/tools/clippy/src/docs/match_single_binding.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for useless match that binds to only one value.
-
-### Why is this bad?
-Readability and needless complexity.
-
-### Known problems
- Suggested replacements may be incorrect when `match`
-is actually binding temporary value, bringing a 'dropped while borrowed' error.
-
-### Example
-```
-match (a, b) {
-    (c, d) => {
-        // useless match
-    }
-}
-```
-
-Use instead:
-```
-let (c, d) = (a, b);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/match_str_case_mismatch.txt b/src/tools/clippy/src/docs/match_str_case_mismatch.txt
deleted file mode 100644
index 19e74c2084e..00000000000
--- a/src/tools/clippy/src/docs/match_str_case_mismatch.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for `match` expressions modifying the case of a string with non-compliant arms
-
-### Why is this bad?
-The arm is unreachable, which is likely a mistake
-
-### Example
-```
-match &*text.to_ascii_lowercase() {
-    "foo" => {},
-    "Bar" => {},
-    _ => {},
-}
-```
-Use instead:
-```
-match &*text.to_ascii_lowercase() {
-    "foo" => {},
-    "bar" => {},
-    _ => {},
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/match_wild_err_arm.txt b/src/tools/clippy/src/docs/match_wild_err_arm.txt
deleted file mode 100644
index f89b3a23a1c..00000000000
--- a/src/tools/clippy/src/docs/match_wild_err_arm.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for arm which matches all errors with `Err(_)`
-and take drastic actions like `panic!`.
-
-### Why is this bad?
-It is generally a bad practice, similar to
-catching all exceptions in java with `catch(Exception)`
-
-### Example
-```
-let x: Result<i32, &str> = Ok(3);
-match x {
-    Ok(_) => println!("ok"),
-    Err(_) => panic!("err"),
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/match_wildcard_for_single_variants.txt b/src/tools/clippy/src/docs/match_wildcard_for_single_variants.txt
deleted file mode 100644
index 25559b9ecdc..00000000000
--- a/src/tools/clippy/src/docs/match_wildcard_for_single_variants.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for wildcard enum matches for a single variant.
-
-### Why is this bad?
-New enum variants added by library updates can be missed.
-
-### Known problems
-Suggested replacements may not use correct path to enum
-if it's not present in the current scope.
-
-### Example
-```
-match x {
-    Foo::A => {},
-    Foo::B => {},
-    _ => {},
-}
-```
-
-Use instead:
-```
-match x {
-    Foo::A => {},
-    Foo::B => {},
-    Foo::C => {},
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/maybe_infinite_iter.txt b/src/tools/clippy/src/docs/maybe_infinite_iter.txt
deleted file mode 100644
index 1204a49b466..00000000000
--- a/src/tools/clippy/src/docs/maybe_infinite_iter.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for iteration that may be infinite.
-
-### Why is this bad?
-While there may be places where this is acceptable
-(e.g., in event streams), in most cases this is simply an error.
-
-### Known problems
-The code may have a condition to stop iteration, but
-this lint is not clever enough to analyze it.
-
-### Example
-```
-let infinite_iter = 0..;
-[0..].iter().zip(infinite_iter.take_while(|x| *x > 5));
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mem_forget.txt b/src/tools/clippy/src/docs/mem_forget.txt
deleted file mode 100644
index a6888c48fc3..00000000000
--- a/src/tools/clippy/src/docs/mem_forget.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for usage of `std::mem::forget(t)` where `t` is
-`Drop`.
-
-### Why is this bad?
-`std::mem::forget(t)` prevents `t` from running its
-destructor, possibly causing leaks.
-
-### Example
-```
-mem::forget(Rc::new(55))
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mem_replace_option_with_none.txt b/src/tools/clippy/src/docs/mem_replace_option_with_none.txt
deleted file mode 100644
index 7f243d1c165..00000000000
--- a/src/tools/clippy/src/docs/mem_replace_option_with_none.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for `mem::replace()` on an `Option` with
-`None`.
-
-### Why is this bad?
-`Option` already has the method `take()` for
-taking its current value (Some(..) or None) and replacing it with
-`None`.
-
-### Example
-```
-use std::mem;
-
-let mut an_option = Some(0);
-let replaced = mem::replace(&mut an_option, None);
-```
-Is better expressed with:
-```
-let mut an_option = Some(0);
-let taken = an_option.take();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mem_replace_with_default.txt b/src/tools/clippy/src/docs/mem_replace_with_default.txt
deleted file mode 100644
index 24e0913a30c..00000000000
--- a/src/tools/clippy/src/docs/mem_replace_with_default.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for `std::mem::replace` on a value of type
-`T` with `T::default()`.
-
-### Why is this bad?
-`std::mem` module already has the method `take` to
-take the current value and replace it with the default value of that type.
-
-### Example
-```
-let mut text = String::from("foo");
-let replaced = std::mem::replace(&mut text, String::default());
-```
-Is better expressed with:
-```
-let mut text = String::from("foo");
-let taken = std::mem::take(&mut text);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mem_replace_with_uninit.txt b/src/tools/clippy/src/docs/mem_replace_with_uninit.txt
deleted file mode 100644
index 0bb483668ab..00000000000
--- a/src/tools/clippy/src/docs/mem_replace_with_uninit.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for `mem::replace(&mut _, mem::uninitialized())`
-and `mem::replace(&mut _, mem::zeroed())`.
-
-### Why is this bad?
-This will lead to undefined behavior even if the
-value is overwritten later, because the uninitialized value may be
-observed in the case of a panic.
-
-### Example
-```
-use std::mem;
-
-#[allow(deprecated, invalid_value)]
-fn myfunc (v: &mut Vec<i32>) {
-    let taken_v = unsafe { mem::replace(v, mem::uninitialized()) };
-    let new_v = may_panic(taken_v); // undefined behavior on panic
-    mem::forget(mem::replace(v, new_v));
-}
-```
-
-The [take_mut](https://docs.rs/take_mut) crate offers a sound solution,
-at the cost of either lazily creating a replacement value or aborting
-on panic, to ensure that the uninitialized value cannot be observed.
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/min_max.txt b/src/tools/clippy/src/docs/min_max.txt
deleted file mode 100644
index 6acf0f932e9..00000000000
--- a/src/tools/clippy/src/docs/min_max.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for expressions where `std::cmp::min` and `max` are
-used to clamp values, but switched so that the result is constant.
-
-### Why is this bad?
-This is in all probability not the intended outcome. At
-the least it hurts readability of the code.
-
-### Example
-```
-min(0, max(100, x))
-
-// or
-
-x.max(100).min(0)
-```
-It will always be equal to `0`. Probably the author meant to clamp the value
-between 0 and 100, but has erroneously swapped `min` and `max`.
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mismatched_target_os.txt b/src/tools/clippy/src/docs/mismatched_target_os.txt
deleted file mode 100644
index 51e5ec6e7c5..00000000000
--- a/src/tools/clippy/src/docs/mismatched_target_os.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for cfg attributes having operating systems used in target family position.
-
-### Why is this bad?
-The configuration option will not be recognised and the related item will not be included
-by the conditional compilation engine.
-
-### Example
-```
-#[cfg(linux)]
-fn conditional() { }
-```
-
-Use instead:
-```
-#[cfg(target_os = "linux")]
-fn conditional() { }
-
-// or
-
-#[cfg(unix)]
-fn conditional() { }
-```
-Check the [Rust Reference](https://doc.rust-lang.org/reference/conditional-compilation.html#target_os) for more details.
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mismatching_type_param_order.txt b/src/tools/clippy/src/docs/mismatching_type_param_order.txt
deleted file mode 100644
index ffc7f32d0aa..00000000000
--- a/src/tools/clippy/src/docs/mismatching_type_param_order.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-### What it does
-Checks for type parameters which are positioned inconsistently between
-a type definition and impl block. Specifically, a parameter in an impl
-block which has the same name as a parameter in the type def, but is in
-a different place.
-
-### Why is this bad?
-Type parameters are determined by their position rather than name.
-Naming type parameters inconsistently may cause you to refer to the
-wrong type parameter.
-
-### Limitations
-This lint only applies to impl blocks with simple generic params, e.g.
-`A`. If there is anything more complicated, such as a tuple, it will be
-ignored.
-
-### Example
-```
-struct Foo<A, B> {
-    x: A,
-    y: B,
-}
-// inside the impl, B refers to Foo::A
-impl<B, A> Foo<B, A> {}
-```
-Use instead:
-```
-struct Foo<A, B> {
-    x: A,
-    y: B,
-}
-impl<A, B> Foo<A, B> {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/misrefactored_assign_op.txt b/src/tools/clippy/src/docs/misrefactored_assign_op.txt
deleted file mode 100644
index 3d691fe4178..00000000000
--- a/src/tools/clippy/src/docs/misrefactored_assign_op.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for `a op= a op b` or `a op= b op a` patterns.
-
-### Why is this bad?
-Most likely these are bugs where one meant to write `a
-op= b`.
-
-### Known problems
-Clippy cannot know for sure if `a op= a op b` should have
-been `a = a op a op b` or `a = a op b`/`a op= b`. Therefore, it suggests both.
-If `a op= a op b` is really the correct behavior it should be
-written as `a = a op a op b` as it's less confusing.
-
-### Example
-```
-let mut a = 5;
-let b = 2;
-// ...
-a += a + b;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/missing_const_for_fn.txt b/src/tools/clippy/src/docs/missing_const_for_fn.txt
deleted file mode 100644
index 067614d4c46..00000000000
--- a/src/tools/clippy/src/docs/missing_const_for_fn.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-### What it does
-Suggests the use of `const` in functions and methods where possible.
-
-### Why is this bad?
-Not having the function const prevents callers of the function from being const as well.
-
-### Known problems
-Const functions are currently still being worked on, with some features only being available
-on nightly. This lint does not consider all edge cases currently and the suggestions may be
-incorrect if you are using this lint on stable.
-
-Also, the lint only runs one pass over the code. Consider these two non-const functions:
-
-```
-fn a() -> i32 {
-    0
-}
-fn b() -> i32 {
-    a()
-}
-```
-
-When running Clippy, the lint will only suggest to make `a` const, because `b` at this time
-can't be const as it calls a non-const function. Making `a` const and running Clippy again,
-will suggest to make `b` const, too.
-
-### Example
-```
-fn new() -> Self {
-    Self { random_number: 42 }
-}
-```
-
-Could be a const fn:
-
-```
-const fn new() -> Self {
-    Self { random_number: 42 }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/missing_docs_in_private_items.txt b/src/tools/clippy/src/docs/missing_docs_in_private_items.txt
deleted file mode 100644
index 5d37505bb17..00000000000
--- a/src/tools/clippy/src/docs/missing_docs_in_private_items.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-### What it does
-Warns if there is missing doc for any documentable item
-(public or private).
-
-### Why is this bad?
-Doc is good. *rustc* has a `MISSING_DOCS`
-allowed-by-default lint for
-public members, but has no way to enforce documentation of private items.
-This lint fixes that.
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/missing_enforced_import_renames.txt b/src/tools/clippy/src/docs/missing_enforced_import_renames.txt
deleted file mode 100644
index 8f4649bd592..00000000000
--- a/src/tools/clippy/src/docs/missing_enforced_import_renames.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for imports that do not rename the item as specified
-in the `enforce-import-renames` config option.
-
-### Why is this bad?
-Consistency is important, if a project has defined import
-renames they should be followed. More practically, some item names are too
-vague outside of their defining scope this can enforce a more meaningful naming.
-
-### Example
-An example clippy.toml configuration:
-```
-enforced-import-renames = [ { path = "serde_json::Value", rename = "JsonValue" }]
-```
-
-```
-use serde_json::Value;
-```
-Use instead:
-```
-use serde_json::Value as JsonValue;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/missing_errors_doc.txt b/src/tools/clippy/src/docs/missing_errors_doc.txt
deleted file mode 100644
index 028778d85ae..00000000000
--- a/src/tools/clippy/src/docs/missing_errors_doc.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks the doc comments of publicly visible functions that
-return a `Result` type and warns if there is no `# Errors` section.
-
-### Why is this bad?
-Documenting the type of errors that can be returned from a
-function can help callers write code to handle the errors appropriately.
-
-### Examples
-Since the following function returns a `Result` it has an `# Errors` section in
-its doc comment:
-
-```
-/// # Errors
-///
-/// Will return `Err` if `filename` does not exist or the user does not have
-/// permission to read it.
-pub fn read(filename: String) -> io::Result<String> {
-    unimplemented!();
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/missing_inline_in_public_items.txt b/src/tools/clippy/src/docs/missing_inline_in_public_items.txt
deleted file mode 100644
index d90c50fe7f9..00000000000
--- a/src/tools/clippy/src/docs/missing_inline_in_public_items.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-### What it does
-It lints if an exported function, method, trait method with default impl,
-or trait method impl is not `#[inline]`.
-
-### Why is this bad?
-In general, it is not. Functions can be inlined across
-crates when that's profitable as long as any form of LTO is used. When LTO is disabled,
-functions that are not `#[inline]` cannot be inlined across crates. Certain types of crates
-might intend for most of the methods in their public API to be able to be inlined across
-crates even when LTO is disabled. For these types of crates, enabling this lint might make
-sense. It allows the crate to require all exported methods to be `#[inline]` by default, and
-then opt out for specific methods where this might not make sense.
-
-### Example
-```
-pub fn foo() {} // missing #[inline]
-fn ok() {} // ok
-#[inline] pub fn bar() {} // ok
-#[inline(always)] pub fn baz() {} // ok
-
-pub trait Bar {
-  fn bar(); // ok
-  fn def_bar() {} // missing #[inline]
-}
-
-struct Baz;
-impl Baz {
-   fn private() {} // ok
-}
-
-impl Bar for Baz {
-  fn bar() {} // ok - Baz is not exported
-}
-
-pub struct PubBaz;
-impl PubBaz {
-   fn private() {} // ok
-   pub fn not_private() {} // missing #[inline]
-}
-
-impl Bar for PubBaz {
-   fn bar() {} // missing #[inline]
-   fn def_bar() {} // missing #[inline]
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/missing_panics_doc.txt b/src/tools/clippy/src/docs/missing_panics_doc.txt
deleted file mode 100644
index e5e39a82451..00000000000
--- a/src/tools/clippy/src/docs/missing_panics_doc.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks the doc comments of publicly visible functions that
-may panic and warns if there is no `# Panics` section.
-
-### Why is this bad?
-Documenting the scenarios in which panicking occurs
-can help callers who do not want to panic to avoid those situations.
-
-### Examples
-Since the following function may panic it has a `# Panics` section in
-its doc comment:
-
-```
-/// # Panics
-///
-/// Will panic if y is 0
-pub fn divide_by(x: i32, y: i32) -> i32 {
-    if y == 0 {
-        panic!("Cannot divide by 0")
-    } else {
-        x / y
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/missing_safety_doc.txt b/src/tools/clippy/src/docs/missing_safety_doc.txt
deleted file mode 100644
index 6492eb84f63..00000000000
--- a/src/tools/clippy/src/docs/missing_safety_doc.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for the doc comments of publicly visible
-unsafe functions and warns if there is no `# Safety` section.
-
-### Why is this bad?
-Unsafe functions should document their safety
-preconditions, so that users can be sure they are using them safely.
-
-### Examples
-```
-/// This function should really be documented
-pub unsafe fn start_apocalypse(u: &mut Universe) {
-    unimplemented!();
-}
-```
-
-At least write a line about safety:
-
-```
-/// # Safety
-///
-/// This function should not be called before the horsemen are ready.
-pub unsafe fn start_apocalypse(u: &mut Universe) {
-    unimplemented!();
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/missing_spin_loop.txt b/src/tools/clippy/src/docs/missing_spin_loop.txt
deleted file mode 100644
index 3a06a91d718..00000000000
--- a/src/tools/clippy/src/docs/missing_spin_loop.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Check for empty spin loops
-
-### Why is this bad?
-The loop body should have something like `thread::park()` or at least
-`std::hint::spin_loop()` to avoid needlessly burning cycles and conserve
-energy. Perhaps even better use an actual lock, if possible.
-
-### Known problems
-This lint doesn't currently trigger on `while let` or
-`loop { match .. { .. } }` loops, which would be considered idiomatic in
-combination with e.g. `AtomicBool::compare_exchange_weak`.
-
-### Example
-
-```
-use core::sync::atomic::{AtomicBool, Ordering};
-let b = AtomicBool::new(true);
-// give a ref to `b` to another thread,wait for it to become false
-while b.load(Ordering::Acquire) {};
-```
-Use instead:
-```
-while b.load(Ordering::Acquire) {
-    std::hint::spin_loop()
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/missing_trait_methods.txt b/src/tools/clippy/src/docs/missing_trait_methods.txt
deleted file mode 100644
index 788ad764f8c..00000000000
--- a/src/tools/clippy/src/docs/missing_trait_methods.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-### What it does
-Checks if a provided method is used implicitly by a trait
-implementation. A usage example would be a wrapper where every method
-should perform some operation before delegating to the inner type's
-implemenation.
-
-This lint should typically be enabled on a specific trait `impl` item
-rather than globally.
-
-### Why is this bad?
-Indicates that a method is missing.
-
-### Example
-```
-trait Trait {
-    fn required();
-
-    fn provided() {}
-}
-
-#[warn(clippy::missing_trait_methods)]
-impl Trait for Type {
-    fn required() { /* ... */ }
-}
-```
-Use instead:
-```
-trait Trait {
-    fn required();
-
-    fn provided() {}
-}
-
-#[warn(clippy::missing_trait_methods)]
-impl Trait for Type {
-    fn required() { /* ... */ }
-
-    fn provided() { /* ... */ }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mistyped_literal_suffixes.txt b/src/tools/clippy/src/docs/mistyped_literal_suffixes.txt
deleted file mode 100644
index 1760fcbfeac..00000000000
--- a/src/tools/clippy/src/docs/mistyped_literal_suffixes.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Warns for mistyped suffix in literals
-
-### Why is this bad?
-This is most probably a typo
-
-### Known problems
-- Does not match on integers too large to fit in the corresponding unsigned type
-- Does not match on `_127` since that is a valid grouping for decimal and octal numbers
-
-### Example
-```
-`2_32` => `2_i32`
-`250_8 => `250_u8`
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mixed_case_hex_literals.txt b/src/tools/clippy/src/docs/mixed_case_hex_literals.txt
deleted file mode 100644
index d2d01e0c98e..00000000000
--- a/src/tools/clippy/src/docs/mixed_case_hex_literals.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Warns on hexadecimal literals with mixed-case letter
-digits.
-
-### Why is this bad?
-It looks confusing.
-
-### Example
-```
-0x1a9BAcD
-```
-
-Use instead:
-```
-0x1A9BACD
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mixed_read_write_in_expression.txt b/src/tools/clippy/src/docs/mixed_read_write_in_expression.txt
deleted file mode 100644
index 02d1c5d0525..00000000000
--- a/src/tools/clippy/src/docs/mixed_read_write_in_expression.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-### What it does
-Checks for a read and a write to the same variable where
-whether the read occurs before or after the write depends on the evaluation
-order of sub-expressions.
-
-### Why is this bad?
-It is often confusing to read. As described [here](https://doc.rust-lang.org/reference/expressions.html?highlight=subexpression#evaluation-order-of-operands),
-the operands of these expressions are evaluated before applying the effects of the expression.
-
-### Known problems
-Code which intentionally depends on the evaluation
-order, or which is correct for any evaluation order.
-
-### Example
-```
-let mut x = 0;
-
-let a = {
-    x = 1;
-    1
-} + x;
-// Unclear whether a is 1 or 2.
-```
-
-Use instead:
-```
-let tmp = {
-    x = 1;
-    1
-};
-let a = tmp + x;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mod_module_files.txt b/src/tools/clippy/src/docs/mod_module_files.txt
deleted file mode 100644
index 95bca583afd..00000000000
--- a/src/tools/clippy/src/docs/mod_module_files.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks that module layout uses only self named module files, bans `mod.rs` files.
-
-### Why is this bad?
-Having multiple module layout styles in a project can be confusing.
-
-### Example
-```
-src/
-  stuff/
-    stuff_files.rs
-    mod.rs
-  lib.rs
-```
-Use instead:
-```
-src/
-  stuff/
-    stuff_files.rs
-  stuff.rs
-  lib.rs
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/module_inception.txt b/src/tools/clippy/src/docs/module_inception.txt
deleted file mode 100644
index d80a1b8d8fe..00000000000
--- a/src/tools/clippy/src/docs/module_inception.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for modules that have the same name as their
-parent module
-
-### Why is this bad?
-A typical beginner mistake is to have `mod foo;` and
-again `mod foo { ..
-}` in `foo.rs`.
-The expectation is that items inside the inner `mod foo { .. }` are then
-available
-through `foo::x`, but they are only available through
-`foo::foo::x`.
-If this is done on purpose, it would be better to choose a more
-representative module name.
-
-### Example
-```
-// lib.rs
-mod foo;
-// foo.rs
-mod foo {
-    ...
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/module_name_repetitions.txt b/src/tools/clippy/src/docs/module_name_repetitions.txt
deleted file mode 100644
index 3bc05d02780..00000000000
--- a/src/tools/clippy/src/docs/module_name_repetitions.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Detects type names that are prefixed or suffixed by the
-containing module's name.
-
-### Why is this bad?
-It requires the user to type the module name twice.
-
-### Example
-```
-mod cake {
-    struct BlackForestCake;
-}
-```
-
-Use instead:
-```
-mod cake {
-    struct BlackForest;
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/modulo_arithmetic.txt b/src/tools/clippy/src/docs/modulo_arithmetic.txt
deleted file mode 100644
index ff7296f3c5b..00000000000
--- a/src/tools/clippy/src/docs/modulo_arithmetic.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for modulo arithmetic.
-
-### Why is this bad?
-The results of modulo (%) operation might differ
-depending on the language, when negative numbers are involved.
-If you interop with different languages it might be beneficial
-to double check all places that use modulo arithmetic.
-
-For example, in Rust `17 % -3 = 2`, but in Python `17 % -3 = -1`.
-
-### Example
-```
-let x = -17 % 3;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/modulo_one.txt b/src/tools/clippy/src/docs/modulo_one.txt
deleted file mode 100644
index bc8f95b0be6..00000000000
--- a/src/tools/clippy/src/docs/modulo_one.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for getting the remainder of a division by one or minus
-one.
-
-### Why is this bad?
-The result for a divisor of one can only ever be zero; for
-minus one it can cause panic/overflow (if the left operand is the minimal value of
-the respective integer type) or results in zero. No one will write such code
-deliberately, unless trying to win an Underhanded Rust Contest. Even for that
-contest, it's probably a bad idea. Use something more underhanded.
-
-### Example
-```
-let a = x % 1;
-let a = x % -1;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/multi_assignments.txt b/src/tools/clippy/src/docs/multi_assignments.txt
deleted file mode 100644
index ed1f1b420cb..00000000000
--- a/src/tools/clippy/src/docs/multi_assignments.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for nested assignments.
-
-### Why is this bad?
-While this is in most cases already a type mismatch,
-the result of an assignment being `()` can throw off people coming from languages like python or C,
-where such assignments return a copy of the assigned value.
-
-### Example
-```
-a = b = 42;
-```
-Use instead:
-```
-b = 42;
-a = b;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/multiple_crate_versions.txt b/src/tools/clippy/src/docs/multiple_crate_versions.txt
deleted file mode 100644
index cf2d2c6abee..00000000000
--- a/src/tools/clippy/src/docs/multiple_crate_versions.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks to see if multiple versions of a crate are being
-used.
-
-### Why is this bad?
-This bloats the size of targets, and can lead to
-confusing error messages when structs or traits are used interchangeably
-between different versions of a crate.
-
-### Known problems
-Because this can be caused purely by the dependencies
-themselves, it's not always possible to fix this issue.
-
-### Example
-```
-[dependencies]
-ctrlc = "=3.1.0"
-ansi_term = "=0.11.0"
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/multiple_inherent_impl.txt b/src/tools/clippy/src/docs/multiple_inherent_impl.txt
deleted file mode 100644
index 9d42286560c..00000000000
--- a/src/tools/clippy/src/docs/multiple_inherent_impl.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for multiple inherent implementations of a struct
-
-### Why is this bad?
-Splitting the implementation of a type makes the code harder to navigate.
-
-### Example
-```
-struct X;
-impl X {
-    fn one() {}
-}
-impl X {
-    fn other() {}
-}
-```
-
-Could be written:
-
-```
-struct X;
-impl X {
-    fn one() {}
-    fn other() {}
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/must_use_candidate.txt b/src/tools/clippy/src/docs/must_use_candidate.txt
deleted file mode 100644
index 70890346fe6..00000000000
--- a/src/tools/clippy/src/docs/must_use_candidate.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for public functions that have no
-`#[must_use]` attribute, but return something not already marked
-must-use, have no mutable arg and mutate no statics.
-
-### Why is this bad?
-Not bad at all, this lint just shows places where
-you could add the attribute.
-
-### Known problems
-The lint only checks the arguments for mutable
-types without looking if they are actually changed. On the other hand,
-it also ignores a broad range of potentially interesting side effects,
-because we cannot decide whether the programmer intends the function to
-be called for the side effect or the result. Expect many false
-positives. At least we don't lint if the result type is unit or already
-`#[must_use]`.
-
-### Examples
-```
-// this could be annotated with `#[must_use]`.
-fn id<T>(t: T) -> T { t }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/must_use_unit.txt b/src/tools/clippy/src/docs/must_use_unit.txt
deleted file mode 100644
index cabbb23f865..00000000000
--- a/src/tools/clippy/src/docs/must_use_unit.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-### What it does
-Checks for a `#[must_use]` attribute on
-unit-returning functions and methods.
-
-### Why is this bad?
-Unit values are useless. The attribute is likely
-a remnant of a refactoring that removed the return type.
-
-### Examples
-```
-#[must_use]
-fn useless() { }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mut_from_ref.txt b/src/tools/clippy/src/docs/mut_from_ref.txt
deleted file mode 100644
index cc1da12549a..00000000000
--- a/src/tools/clippy/src/docs/mut_from_ref.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-This lint checks for functions that take immutable references and return
-mutable ones. This will not trigger if no unsafe code exists as there
-are multiple safe functions which will do this transformation
-
-To be on the conservative side, if there's at least one mutable
-reference with the output lifetime, this lint will not trigger.
-
-### Why is this bad?
-Creating a mutable reference which can be repeatably derived from an
-immutable reference is unsound as it allows creating multiple live
-mutable references to the same object.
-
-This [error](https://github.com/rust-lang/rust/issues/39465) actually
-lead to an interim Rust release 1.15.1.
-
-### Known problems
-This pattern is used by memory allocators to allow allocating multiple
-objects while returning mutable references to each one. So long as
-different mutable references are returned each time such a function may
-be safe.
-
-### Example
-```
-fn foo(&Foo) -> &mut Bar { .. }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mut_mut.txt b/src/tools/clippy/src/docs/mut_mut.txt
deleted file mode 100644
index 0bd34dd24b2..00000000000
--- a/src/tools/clippy/src/docs/mut_mut.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for instances of `mut mut` references.
-
-### Why is this bad?
-Multiple `mut`s don't add anything meaningful to the
-source. This is either a copy'n'paste error, or it shows a fundamental
-misunderstanding of references.
-
-### Example
-```
-let x = &mut &mut y;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mut_mutex_lock.txt b/src/tools/clippy/src/docs/mut_mutex_lock.txt
deleted file mode 100644
index 5e9ad8a3f17..00000000000
--- a/src/tools/clippy/src/docs/mut_mutex_lock.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Checks for `&mut Mutex::lock` calls
-
-### Why is this bad?
-`Mutex::lock` is less efficient than
-calling `Mutex::get_mut`. In addition you also have a statically
-guarantee that the mutex isn't locked, instead of just a runtime
-guarantee.
-
-### Example
-```
-use std::sync::{Arc, Mutex};
-
-let mut value_rc = Arc::new(Mutex::new(42_u8));
-let value_mutex = Arc::get_mut(&mut value_rc).unwrap();
-
-let mut value = value_mutex.lock().unwrap();
-*value += 1;
-```
-Use instead:
-```
-use std::sync::{Arc, Mutex};
-
-let mut value_rc = Arc::new(Mutex::new(42_u8));
-let value_mutex = Arc::get_mut(&mut value_rc).unwrap();
-
-let value = value_mutex.get_mut().unwrap();
-*value += 1;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mut_range_bound.txt b/src/tools/clippy/src/docs/mut_range_bound.txt
deleted file mode 100644
index e9c38a543b1..00000000000
--- a/src/tools/clippy/src/docs/mut_range_bound.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Checks for loops which have a range bound that is a mutable variable
-
-### Why is this bad?
-One might think that modifying the mutable variable changes the loop bounds
-
-### Known problems
-False positive when mutation is followed by a `break`, but the `break` is not immediately
-after the mutation:
-
-```
-let mut x = 5;
-for _ in 0..x {
-    x += 1; // x is a range bound that is mutated
-    ..; // some other expression
-    break; // leaves the loop, so mutation is not an issue
-}
-```
-
-False positive on nested loops ([#6072](https://github.com/rust-lang/rust-clippy/issues/6072))
-
-### Example
-```
-let mut foo = 42;
-for i in 0..foo {
-    foo -= 1;
-    println!("{}", i); // prints numbers from 0 to 42, not 0 to 21
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mutable_key_type.txt b/src/tools/clippy/src/docs/mutable_key_type.txt
deleted file mode 100644
index 15fe34f2bb5..00000000000
--- a/src/tools/clippy/src/docs/mutable_key_type.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-### What it does
-Checks for sets/maps with mutable key types.
-
-### Why is this bad?
-All of `HashMap`, `HashSet`, `BTreeMap` and
-`BtreeSet` rely on either the hash or the order of keys be unchanging,
-so having types with interior mutability is a bad idea.
-
-### Known problems
-
-#### False Positives
-It's correct to use a struct that contains interior mutability as a key, when its
-implementation of `Hash` or `Ord` doesn't access any of the interior mutable types.
-However, this lint is unable to recognize this, so it will often cause false positives in
-theses cases.  The `bytes` crate is a great example of this.
-
-#### False Negatives
-For custom `struct`s/`enum`s, this lint is unable to check for interior mutability behind
-indirection.  For example, `struct BadKey<'a>(&'a Cell<usize>)` will be seen as immutable
-and cause a false negative if its implementation of `Hash`/`Ord` accesses the `Cell`.
-
-This lint does check a few cases for indirection.  Firstly, using some standard library
-types (`Option`, `Result`, `Box`, `Rc`, `Arc`, `Vec`, `VecDeque`, `BTreeMap` and
-`BTreeSet`) directly as keys (e.g. in `HashMap<Box<Cell<usize>>, ()>`) **will** trigger the
-lint, because the impls of `Hash`/`Ord` for these types directly call `Hash`/`Ord` on their
-contained type.
-
-Secondly, the implementations of `Hash` and `Ord` for raw pointers (`*const T` or `*mut T`)
-apply only to the **address** of the contained value.  Therefore, interior mutability
-behind raw pointers (e.g. in `HashSet<*mut Cell<usize>>`) can't impact the value of `Hash`
-or `Ord`, and therefore will not trigger this link.  For more info, see issue
-[#6745](https://github.com/rust-lang/rust-clippy/issues/6745).
-
-### Example
-```
-use std::cmp::{PartialEq, Eq};
-use std::collections::HashSet;
-use std::hash::{Hash, Hasher};
-use std::sync::atomic::AtomicUsize;
-
-struct Bad(AtomicUsize);
-impl PartialEq for Bad {
-    fn eq(&self, rhs: &Self) -> bool {
-         ..
-; unimplemented!();
-    }
-}
-
-impl Eq for Bad {}
-
-impl Hash for Bad {
-    fn hash<H: Hasher>(&self, h: &mut H) {
-        ..
-; unimplemented!();
-    }
-}
-
-fn main() {
-    let _: HashSet<Bad> = HashSet::new();
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mutex_atomic.txt b/src/tools/clippy/src/docs/mutex_atomic.txt
deleted file mode 100644
index 062ac8b323b..00000000000
--- a/src/tools/clippy/src/docs/mutex_atomic.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for usages of `Mutex<X>` where an atomic will do.
-
-### Why is this bad?
-Using a mutex just to make access to a plain bool or
-reference sequential is shooting flies with cannons.
-`std::sync::atomic::AtomicBool` and `std::sync::atomic::AtomicPtr` are leaner and
-faster.
-
-### Known problems
-This lint cannot detect if the mutex is actually used
-for waiting before a critical section.
-
-### Example
-```
-let x = Mutex::new(&y);
-```
-
-Use instead:
-```
-let x = AtomicBool::new(y);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/mutex_integer.txt b/src/tools/clippy/src/docs/mutex_integer.txt
deleted file mode 100644
index f9dbdfb904c..00000000000
--- a/src/tools/clippy/src/docs/mutex_integer.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for usages of `Mutex<X>` where `X` is an integral
-type.
-
-### Why is this bad?
-Using a mutex just to make access to a plain integer
-sequential is
-shooting flies with cannons. `std::sync::atomic::AtomicUsize` is leaner and faster.
-
-### Known problems
-This lint cannot detect if the mutex is actually used
-for waiting before a critical section.
-
-### Example
-```
-let x = Mutex::new(0usize);
-```
-
-Use instead:
-```
-let x = AtomicUsize::new(0usize);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/naive_bytecount.txt b/src/tools/clippy/src/docs/naive_bytecount.txt
deleted file mode 100644
index 24659dc79ae..00000000000
--- a/src/tools/clippy/src/docs/naive_bytecount.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for naive byte counts
-
-### Why is this bad?
-The [`bytecount`](https://crates.io/crates/bytecount)
-crate has methods to count your bytes faster, especially for large slices.
-
-### Known problems
-If you have predominantly small slices, the
-`bytecount::count(..)` method may actually be slower. However, if you can
-ensure that less than 2³²-1 matches arise, the `naive_count_32(..)` can be
-faster in those cases.
-
-### Example
-```
-let count = vec.iter().filter(|x| **x == 0u8).count();
-```
-
-Use instead:
-```
-let count = bytecount::count(&vec, 0u8);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_arbitrary_self_type.txt b/src/tools/clippy/src/docs/needless_arbitrary_self_type.txt
deleted file mode 100644
index 8216a3a3fb6..00000000000
--- a/src/tools/clippy/src/docs/needless_arbitrary_self_type.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-### What it does
-The lint checks for `self` in fn parameters that
-specify the `Self`-type explicitly
-### Why is this bad?
-Increases the amount and decreases the readability of code
-
-### Example
-```
-enum ValType {
-    I32,
-    I64,
-    F32,
-    F64,
-}
-
-impl ValType {
-    pub fn bytes(self: Self) -> usize {
-        match self {
-            Self::I32 | Self::F32 => 4,
-            Self::I64 | Self::F64 => 8,
-        }
-    }
-}
-```
-
-Could be rewritten as
-
-```
-enum ValType {
-    I32,
-    I64,
-    F32,
-    F64,
-}
-
-impl ValType {
-    pub fn bytes(self) -> usize {
-        match self {
-            Self::I32 | Self::F32 => 4,
-            Self::I64 | Self::F64 => 8,
-        }
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_bitwise_bool.txt b/src/tools/clippy/src/docs/needless_bitwise_bool.txt
deleted file mode 100644
index fcd7b730aaa..00000000000
--- a/src/tools/clippy/src/docs/needless_bitwise_bool.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for uses of bitwise and/or operators between booleans, where performance may be improved by using
-a lazy and.
-
-### Why is this bad?
-The bitwise operators do not support short-circuiting, so it may hinder code performance.
-Additionally, boolean logic "masked" as bitwise logic is not caught by lints like `unnecessary_fold`
-
-### Known problems
-This lint evaluates only when the right side is determined to have no side effects. At this time, that
-determination is quite conservative.
-
-### Example
-```
-let (x,y) = (true, false);
-if x & !y {} // where both x and y are booleans
-```
-Use instead:
-```
-let (x,y) = (true, false);
-if x && !y {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_bool.txt b/src/tools/clippy/src/docs/needless_bool.txt
deleted file mode 100644
index b5c78871f14..00000000000
--- a/src/tools/clippy/src/docs/needless_bool.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for expressions of the form `if c { true } else {
-false }` (or vice versa) and suggests using the condition directly.
-
-### Why is this bad?
-Redundant code.
-
-### Known problems
-Maybe false positives: Sometimes, the two branches are
-painstakingly documented (which we, of course, do not detect), so they *may*
-have some value. Even then, the documentation can be rewritten to match the
-shorter code.
-
-### Example
-```
-if x {
-    false
-} else {
-    true
-}
-```
-
-Use instead:
-```
-!x
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_borrow.txt b/src/tools/clippy/src/docs/needless_borrow.txt
deleted file mode 100644
index 4debcf47372..00000000000
--- a/src/tools/clippy/src/docs/needless_borrow.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for address of operations (`&`) that are going to
-be dereferenced immediately by the compiler.
-
-### Why is this bad?
-Suggests that the receiver of the expression borrows
-the expression.
-
-### Example
-```
-fn fun(_a: &i32) {}
-
-let x: &i32 = &&&&&&5;
-fun(&x);
-```
-
-Use instead:
-```
-let x: &i32 = &5;
-fun(x);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_borrowed_reference.txt b/src/tools/clippy/src/docs/needless_borrowed_reference.txt
deleted file mode 100644
index 152459ba1c9..00000000000
--- a/src/tools/clippy/src/docs/needless_borrowed_reference.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for bindings that needlessly destructure a reference and borrow the inner
-value with `&ref`.
-
-### Why is this bad?
-This pattern has no effect in almost all cases.
-
-### Example
-```
-let mut v = Vec::<String>::new();
-v.iter_mut().filter(|&ref a| a.is_empty());
-
-if let &[ref first, ref second] = v.as_slice() {}
-```
-
-Use instead:
-```
-let mut v = Vec::<String>::new();
-v.iter_mut().filter(|a| a.is_empty());
-
-if let [first, second] = v.as_slice() {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_collect.txt b/src/tools/clippy/src/docs/needless_collect.txt
deleted file mode 100644
index 275c39afc9d..00000000000
--- a/src/tools/clippy/src/docs/needless_collect.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Checks for functions collecting an iterator when collect
-is not needed.
-
-### Why is this bad?
-`collect` causes the allocation of a new data structure,
-when this allocation may not be needed.
-
-### Example
-```
-let len = iterator.clone().collect::<Vec<_>>().len();
-// should be
-let len = iterator.count();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_continue.txt b/src/tools/clippy/src/docs/needless_continue.txt
deleted file mode 100644
index 2cee621c1af..00000000000
--- a/src/tools/clippy/src/docs/needless_continue.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-### What it does
-The lint checks for `if`-statements appearing in loops
-that contain a `continue` statement in either their main blocks or their
-`else`-blocks, when omitting the `else`-block possibly with some
-rearrangement of code can make the code easier to understand.
-
-### Why is this bad?
-Having explicit `else` blocks for `if` statements
-containing `continue` in their THEN branch adds unnecessary branching and
-nesting to the code. Having an else block containing just `continue` can
-also be better written by grouping the statements following the whole `if`
-statement within the THEN block and omitting the else block completely.
-
-### Example
-```
-while condition() {
-    update_condition();
-    if x {
-        // ...
-    } else {
-        continue;
-    }
-    println!("Hello, world");
-}
-```
-
-Could be rewritten as
-
-```
-while condition() {
-    update_condition();
-    if x {
-        // ...
-        println!("Hello, world");
-    }
-}
-```
-
-As another example, the following code
-
-```
-loop {
-    if waiting() {
-        continue;
-    } else {
-        // Do something useful
-    }
-    # break;
-}
-```
-Could be rewritten as
-
-```
-loop {
-    if waiting() {
-        continue;
-    }
-    // Do something useful
-    # break;
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_doctest_main.txt b/src/tools/clippy/src/docs/needless_doctest_main.txt
deleted file mode 100644
index 8f91a7baa71..00000000000
--- a/src/tools/clippy/src/docs/needless_doctest_main.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for `fn main() { .. }` in doctests
-
-### Why is this bad?
-The test can be shorter (and likely more readable)
-if the `fn main()` is left implicit.
-
-### Examples
-```
-/// An example of a doctest with a `main()` function
-///
-/// # Examples
-///
-/// ```
-/// fn main() {
-///     // this needs not be in an `fn`
-/// }
-/// ```
-fn needless_main() {
-    unimplemented!();
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_for_each.txt b/src/tools/clippy/src/docs/needless_for_each.txt
deleted file mode 100644
index 9ae6dd360c8..00000000000
--- a/src/tools/clippy/src/docs/needless_for_each.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for usage of `for_each` that would be more simply written as a
-`for` loop.
-
-### Why is this bad?
-`for_each` may be used after applying iterator transformers like
-`filter` for better readability and performance. It may also be used to fit a simple
-operation on one line.
-But when none of these apply, a simple `for` loop is more idiomatic.
-
-### Example
-```
-let v = vec![0, 1, 2];
-v.iter().for_each(|elem| {
-    println!("{}", elem);
-})
-```
-Use instead:
-```
-let v = vec![0, 1, 2];
-for elem in v.iter() {
-    println!("{}", elem);
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_late_init.txt b/src/tools/clippy/src/docs/needless_late_init.txt
deleted file mode 100644
index 9e7bbcea998..00000000000
--- a/src/tools/clippy/src/docs/needless_late_init.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-### What it does
-Checks for late initializations that can be replaced by a `let` statement
-with an initializer.
-
-### Why is this bad?
-Assigning in the `let` statement is less repetitive.
-
-### Example
-```
-let a;
-a = 1;
-
-let b;
-match 3 {
-    0 => b = "zero",
-    1 => b = "one",
-    _ => b = "many",
-}
-
-let c;
-if true {
-    c = 1;
-} else {
-    c = -1;
-}
-```
-Use instead:
-```
-let a = 1;
-
-let b = match 3 {
-    0 => "zero",
-    1 => "one",
-    _ => "many",
-};
-
-let c = if true {
-    1
-} else {
-    -1
-};
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_lifetimes.txt b/src/tools/clippy/src/docs/needless_lifetimes.txt
deleted file mode 100644
index b280caa66b5..00000000000
--- a/src/tools/clippy/src/docs/needless_lifetimes.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Checks for lifetime annotations which can be removed by
-relying on lifetime elision.
-
-### Why is this bad?
-The additional lifetimes make the code look more
-complicated, while there is nothing out of the ordinary going on. Removing
-them leads to more readable code.
-
-### Known problems
-- We bail out if the function has a `where` clause where lifetimes
-are mentioned due to potential false positives.
-- Lifetime bounds such as `impl Foo + 'a` and `T: 'a` must be elided with the
-placeholder notation `'_` because the fully elided notation leaves the type bound to `'static`.
-
-### Example
-```
-// Unnecessary lifetime annotations
-fn in_and_out<'a>(x: &'a u8, y: u8) -> &'a u8 {
-    x
-}
-```
-
-Use instead:
-```
-fn elided(x: &u8, y: u8) -> &u8 {
-    x
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_match.txt b/src/tools/clippy/src/docs/needless_match.txt
deleted file mode 100644
index 92b40a5df64..00000000000
--- a/src/tools/clippy/src/docs/needless_match.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-### What it does
-Checks for unnecessary `match` or match-like `if let` returns for `Option` and `Result`
-when function signatures are the same.
-
-### Why is this bad?
-This `match` block does nothing and might not be what the coder intended.
-
-### Example
-```
-fn foo() -> Result<(), i32> {
-    match result {
-        Ok(val) => Ok(val),
-        Err(err) => Err(err),
-    }
-}
-
-fn bar() -> Option<i32> {
-    if let Some(val) = option {
-        Some(val)
-    } else {
-        None
-    }
-}
-```
-
-Could be replaced as
-
-```
-fn foo() -> Result<(), i32> {
-    result
-}
-
-fn bar() -> Option<i32> {
-    option
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_option_as_deref.txt b/src/tools/clippy/src/docs/needless_option_as_deref.txt
deleted file mode 100644
index 226396c97ac..00000000000
--- a/src/tools/clippy/src/docs/needless_option_as_deref.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for no-op uses of `Option::{as_deref, as_deref_mut}`,
-for example, `Option<&T>::as_deref()` returns the same type.
-
-### Why is this bad?
-Redundant code and improving readability.
-
-### Example
-```
-let a = Some(&1);
-let b = a.as_deref(); // goes from Option<&i32> to Option<&i32>
-```
-
-Use instead:
-```
-let a = Some(&1);
-let b = a;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_option_take.txt b/src/tools/clippy/src/docs/needless_option_take.txt
deleted file mode 100644
index 6bac65a13b5..00000000000
--- a/src/tools/clippy/src/docs/needless_option_take.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for calling `take` function after `as_ref`.
-
-### Why is this bad?
-Redundant code. `take` writes `None` to its argument.
-In this case the modification is useless as it's a temporary that cannot be read from afterwards.
-
-### Example
-```
-let x = Some(3);
-x.as_ref().take();
-```
-Use instead:
-```
-let x = Some(3);
-x.as_ref();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_parens_on_range_literals.txt b/src/tools/clippy/src/docs/needless_parens_on_range_literals.txt
deleted file mode 100644
index 85fab10cb5f..00000000000
--- a/src/tools/clippy/src/docs/needless_parens_on_range_literals.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-The lint checks for parenthesis on literals in range statements that are
-superfluous.
-
-### Why is this bad?
-Having superfluous parenthesis makes the code less readable
-overhead when reading.
-
-### Example
-
-```
-for i in (0)..10 {
-  println!("{i}");
-}
-```
-
-Use instead:
-
-```
-for i in 0..10 {
-  println!("{i}");
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_pass_by_value.txt b/src/tools/clippy/src/docs/needless_pass_by_value.txt
deleted file mode 100644
index 58c420b19f6..00000000000
--- a/src/tools/clippy/src/docs/needless_pass_by_value.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for functions taking arguments by value, but not
-consuming them in its
-body.
-
-### Why is this bad?
-Taking arguments by reference is more flexible and can
-sometimes avoid
-unnecessary allocations.
-
-### Known problems
-* This lint suggests taking an argument by reference,
-however sometimes it is better to let users decide the argument type
-(by using `Borrow` trait, for example), depending on how the function is used.
-
-### Example
-```
-fn foo(v: Vec<i32>) {
-    assert_eq!(v.len(), 42);
-}
-```
-should be
-```
-fn foo(v: &[i32]) {
-    assert_eq!(v.len(), 42);
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_question_mark.txt b/src/tools/clippy/src/docs/needless_question_mark.txt
deleted file mode 100644
index 540739fd45f..00000000000
--- a/src/tools/clippy/src/docs/needless_question_mark.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-### What it does
-Suggests alternatives for useless applications of `?` in terminating expressions
-
-### Why is this bad?
-There's no reason to use `?` to short-circuit when execution of the body will end there anyway.
-
-### Example
-```
-struct TO {
-    magic: Option<usize>,
-}
-
-fn f(to: TO) -> Option<usize> {
-    Some(to.magic?)
-}
-
-struct TR {
-    magic: Result<usize, bool>,
-}
-
-fn g(tr: Result<TR, bool>) -> Result<usize, bool> {
-    tr.and_then(|t| Ok(t.magic?))
-}
-
-```
-Use instead:
-```
-struct TO {
-    magic: Option<usize>,
-}
-
-fn f(to: TO) -> Option<usize> {
-   to.magic
-}
-
-struct TR {
-    magic: Result<usize, bool>,
-}
-
-fn g(tr: Result<TR, bool>) -> Result<usize, bool> {
-    tr.and_then(|t| t.magic)
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_range_loop.txt b/src/tools/clippy/src/docs/needless_range_loop.txt
deleted file mode 100644
index 583c09b2849..00000000000
--- a/src/tools/clippy/src/docs/needless_range_loop.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for looping over the range of `0..len` of some
-collection just to get the values by index.
-
-### Why is this bad?
-Just iterating the collection itself makes the intent
-more clear and is probably faster.
-
-### Example
-```
-let vec = vec!['a', 'b', 'c'];
-for i in 0..vec.len() {
-    println!("{}", vec[i]);
-}
-```
-
-Use instead:
-```
-let vec = vec!['a', 'b', 'c'];
-for i in vec {
-    println!("{}", i);
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_return.txt b/src/tools/clippy/src/docs/needless_return.txt
deleted file mode 100644
index 48782cb0ca8..00000000000
--- a/src/tools/clippy/src/docs/needless_return.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for return statements at the end of a block.
-
-### Why is this bad?
-Removing the `return` and semicolon will make the code
-more rusty.
-
-### Example
-```
-fn foo(x: usize) -> usize {
-    return x;
-}
-```
-simplify to
-```
-fn foo(x: usize) -> usize {
-    x
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_splitn.txt b/src/tools/clippy/src/docs/needless_splitn.txt
deleted file mode 100644
index b10a84fbc42..00000000000
--- a/src/tools/clippy/src/docs/needless_splitn.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for usages of `str::splitn` (or `str::rsplitn`) where using `str::split` would be the same.
-### Why is this bad?
-The function `split` is simpler and there is no performance difference in these cases, considering
-that both functions return a lazy iterator.
-### Example
-```
-let str = "key=value=add";
-let _ = str.splitn(3, '=').next().unwrap();
-```
-
-Use instead:
-```
-let str = "key=value=add";
-let _ = str.split('=').next().unwrap();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_update.txt b/src/tools/clippy/src/docs/needless_update.txt
deleted file mode 100644
index 82adabf6482..00000000000
--- a/src/tools/clippy/src/docs/needless_update.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-### What it does
-Checks for needlessly including a base struct on update
-when all fields are changed anyway.
-
-This lint is not applied to structs marked with
-[non_exhaustive](https://doc.rust-lang.org/reference/attributes/type_system.html).
-
-### Why is this bad?
-This will cost resources (because the base has to be
-somewhere), and make the code less readable.
-
-### Example
-```
-Point {
-    x: 1,
-    y: 1,
-    z: 1,
-    ..zero_point
-};
-```
-
-Use instead:
-```
-// Missing field `z`
-Point {
-    x: 1,
-    y: 1,
-    ..zero_point
-};
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/neg_cmp_op_on_partial_ord.txt b/src/tools/clippy/src/docs/neg_cmp_op_on_partial_ord.txt
deleted file mode 100644
index fa55c6cfd74..00000000000
--- a/src/tools/clippy/src/docs/neg_cmp_op_on_partial_ord.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for the usage of negated comparison operators on types which only implement
-`PartialOrd` (e.g., `f64`).
-
-### Why is this bad?
-These operators make it easy to forget that the underlying types actually allow not only three
-potential Orderings (Less, Equal, Greater) but also a fourth one (Uncomparable). This is
-especially easy to miss if the operator based comparison result is negated.
-
-### Example
-```
-let a = 1.0;
-let b = f64::NAN;
-
-let not_less_or_equal = !(a <= b);
-```
-
-Use instead:
-```
-use std::cmp::Ordering;
-
-let _not_less_or_equal = match a.partial_cmp(&b) {
-    None | Some(Ordering::Greater) => true,
-    _ => false,
-};
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/neg_multiply.txt b/src/tools/clippy/src/docs/neg_multiply.txt
deleted file mode 100644
index 4e8b096eb9c..00000000000
--- a/src/tools/clippy/src/docs/neg_multiply.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for multiplication by -1 as a form of negation.
-
-### Why is this bad?
-It's more readable to just negate.
-
-### Known problems
-This only catches integers (for now).
-
-### Example
-```
-let a = x * -1;
-```
-
-Use instead:
-```
-let a = -x;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/negative_feature_names.txt b/src/tools/clippy/src/docs/negative_feature_names.txt
deleted file mode 100644
index 01ee9efb318..00000000000
--- a/src/tools/clippy/src/docs/negative_feature_names.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for negative feature names with prefix `no-` or `not-`
-
-### Why is this bad?
-Features are supposed to be additive, and negatively-named features violate it.
-
-### Example
-```
-[features]
-default = []
-no-abc = []
-not-def = []
-
-```
-Use instead:
-```
-[features]
-default = ["abc", "def"]
-abc = []
-def = []
-
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/never_loop.txt b/src/tools/clippy/src/docs/never_loop.txt
deleted file mode 100644
index 737ccf415cb..00000000000
--- a/src/tools/clippy/src/docs/never_loop.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for loops that will always `break`, `return` or
-`continue` an outer loop.
-
-### Why is this bad?
-This loop never loops, all it does is obfuscating the
-code.
-
-### Example
-```
-loop {
-    ..;
-    break;
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/new_ret_no_self.txt b/src/tools/clippy/src/docs/new_ret_no_self.txt
deleted file mode 100644
index 291bad24a64..00000000000
--- a/src/tools/clippy/src/docs/new_ret_no_self.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-### What it does
-Checks for `new` not returning a type that contains `Self`.
-
-### Why is this bad?
-As a convention, `new` methods are used to make a new
-instance of a type.
-
-### Example
-In an impl block:
-```
-impl Foo {
-    fn new() -> NotAFoo {
-    }
-}
-```
-
-```
-struct Bar(Foo);
-impl Foo {
-    // Bad. The type name must contain `Self`
-    fn new() -> Bar {
-    }
-}
-```
-
-```
-impl Foo {
-    // Good. Return type contains `Self`
-    fn new() -> Result<Foo, FooError> {
-    }
-}
-```
-
-Or in a trait definition:
-```
-pub trait Trait {
-    // Bad. The type name must contain `Self`
-    fn new();
-}
-```
-
-```
-pub trait Trait {
-    // Good. Return type contains `Self`
-    fn new() -> Self;
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/new_without_default.txt b/src/tools/clippy/src/docs/new_without_default.txt
deleted file mode 100644
index 662d39c8efd..00000000000
--- a/src/tools/clippy/src/docs/new_without_default.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-### What it does
-Checks for public types with a `pub fn new() -> Self` method and no
-implementation of
-[`Default`](https://doc.rust-lang.org/std/default/trait.Default.html).
-
-### Why is this bad?
-The user might expect to be able to use
-[`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the
-type can be constructed without arguments.
-
-### Example
-```
-pub struct Foo(Bar);
-
-impl Foo {
-    pub fn new() -> Self {
-        Foo(Bar::new())
-    }
-}
-```
-
-To fix the lint, add a `Default` implementation that delegates to `new`:
-
-```
-pub struct Foo(Bar);
-
-impl Default for Foo {
-    fn default() -> Self {
-        Foo::new()
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/no_effect.txt b/src/tools/clippy/src/docs/no_effect.txt
deleted file mode 100644
index d4cc08fa8a7..00000000000
--- a/src/tools/clippy/src/docs/no_effect.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for statements which have no effect.
-
-### Why is this bad?
-Unlike dead code, these statements are actually
-executed. However, as they have no effect, all they do is make the code less
-readable.
-
-### Example
-```
-0;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/no_effect_replace.txt b/src/tools/clippy/src/docs/no_effect_replace.txt
deleted file mode 100644
index 646d45287ef..00000000000
--- a/src/tools/clippy/src/docs/no_effect_replace.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-### What it does
-Checks for `replace` statements which have no effect.
-
-### Why is this bad?
-It's either a mistake or confusing.
-
-### Example
-```
-"1234".replace("12", "12");
-"1234".replacen("12", "12", 1);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/no_effect_underscore_binding.txt b/src/tools/clippy/src/docs/no_effect_underscore_binding.txt
deleted file mode 100644
index 972f60dd01e..00000000000
--- a/src/tools/clippy/src/docs/no_effect_underscore_binding.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for binding to underscore prefixed variable without side-effects.
-
-### Why is this bad?
-Unlike dead code, these bindings are actually
-executed. However, as they have no effect and shouldn't be used further on, all they
-do is make the code less readable.
-
-### Known problems
-Further usage of this variable is not checked, which can lead to false positives if it is
-used later in the code.
-
-### Example
-```
-let _i_serve_no_purpose = 1;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/non_ascii_literal.txt b/src/tools/clippy/src/docs/non_ascii_literal.txt
deleted file mode 100644
index 164902b4726..00000000000
--- a/src/tools/clippy/src/docs/non_ascii_literal.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for non-ASCII characters in string and char literals.
-
-### Why is this bad?
-Yeah, we know, the 90's called and wanted their charset
-back. Even so, there still are editors and other programs out there that
-don't work well with Unicode. So if the code is meant to be used
-internationally, on multiple operating systems, or has other portability
-requirements, activating this lint could be useful.
-
-### Example
-```
-let x = String::from("€");
-```
-
-Use instead:
-```
-let x = String::from("\u{20ac}");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/non_octal_unix_permissions.txt b/src/tools/clippy/src/docs/non_octal_unix_permissions.txt
deleted file mode 100644
index 4a468e94db1..00000000000
--- a/src/tools/clippy/src/docs/non_octal_unix_permissions.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for non-octal values used to set Unix file permissions.
-
-### Why is this bad?
-They will be converted into octal, creating potentially
-unintended file permissions.
-
-### Example
-```
-use std::fs::OpenOptions;
-use std::os::unix::fs::OpenOptionsExt;
-
-let mut options = OpenOptions::new();
-options.mode(644);
-```
-Use instead:
-```
-use std::fs::OpenOptions;
-use std::os::unix::fs::OpenOptionsExt;
-
-let mut options = OpenOptions::new();
-options.mode(0o644);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/non_send_fields_in_send_ty.txt b/src/tools/clippy/src/docs/non_send_fields_in_send_ty.txt
deleted file mode 100644
index 11e6f6e162c..00000000000
--- a/src/tools/clippy/src/docs/non_send_fields_in_send_ty.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-### What it does
-This lint warns about a `Send` implementation for a type that
-contains fields that are not safe to be sent across threads.
-It tries to detect fields that can cause a soundness issue
-when sent to another thread (e.g., `Rc`) while allowing `!Send` fields
-that are expected to exist in a `Send` type, such as raw pointers.
-
-### Why is this bad?
-Sending the struct to another thread effectively sends all of its fields,
-and the fields that do not implement `Send` can lead to soundness bugs
-such as data races when accessed in a thread
-that is different from the thread that created it.
-
-See:
-* [*The Rustonomicon* about *Send and Sync*](https://doc.rust-lang.org/nomicon/send-and-sync.html)
-* [The documentation of `Send`](https://doc.rust-lang.org/std/marker/trait.Send.html)
-
-### Known Problems
-This lint relies on heuristics to distinguish types that are actually
-unsafe to be sent across threads and `!Send` types that are expected to
-exist in  `Send` type. Its rule can filter out basic cases such as
-`Vec<*const T>`, but it's not perfect. Feel free to create an issue if
-you have a suggestion on how this heuristic can be improved.
-
-### Example
-```
-struct ExampleStruct<T> {
-    rc_is_not_send: Rc<String>,
-    unbounded_generic_field: T,
-}
-
-// This impl is unsound because it allows sending `!Send` types through `ExampleStruct`
-unsafe impl<T> Send for ExampleStruct<T> {}
-```
-Use thread-safe types like [`std::sync::Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html)
-or specify correct bounds on generic type parameters (`T: Send`).
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/nonminimal_bool.txt b/src/tools/clippy/src/docs/nonminimal_bool.txt
deleted file mode 100644
index 488980ddf02..00000000000
--- a/src/tools/clippy/src/docs/nonminimal_bool.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for boolean expressions that can be written more
-concisely.
-
-### Why is this bad?
-Readability of boolean expressions suffers from
-unnecessary duplication.
-
-### Known problems
-Ignores short circuiting behavior of `||` and
-`&&`. Ignores `|`, `&` and `^`.
-
-### Example
-```
-if a && true {}
-if !(a == b) {}
-```
-
-Use instead:
-```
-if a {}
-if a != b {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/nonsensical_open_options.txt b/src/tools/clippy/src/docs/nonsensical_open_options.txt
deleted file mode 100644
index 7a95443b51a..00000000000
--- a/src/tools/clippy/src/docs/nonsensical_open_options.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Checks for duplicate open options as well as combinations
-that make no sense.
-
-### Why is this bad?
-In the best case, the code will be harder to read than
-necessary. I don't know the worst case.
-
-### Example
-```
-use std::fs::OpenOptions;
-
-OpenOptions::new().read(true).truncate(true);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/nonstandard_macro_braces.txt b/src/tools/clippy/src/docs/nonstandard_macro_braces.txt
deleted file mode 100644
index 7e8d0d2d33b..00000000000
--- a/src/tools/clippy/src/docs/nonstandard_macro_braces.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks that common macros are used with consistent bracing.
-
-### Why is this bad?
-This is mostly a consistency lint although using () or []
-doesn't give you a semicolon in item position, which can be unexpected.
-
-### Example
-```
-vec!{1, 2, 3};
-```
-Use instead:
-```
-vec![1, 2, 3];
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/not_unsafe_ptr_arg_deref.txt b/src/tools/clippy/src/docs/not_unsafe_ptr_arg_deref.txt
deleted file mode 100644
index 31355fbb7b6..00000000000
--- a/src/tools/clippy/src/docs/not_unsafe_ptr_arg_deref.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-### What it does
-Checks for public functions that dereference raw pointer
-arguments but are not marked `unsafe`.
-
-### Why is this bad?
-The function should probably be marked `unsafe`, since
-for an arbitrary raw pointer, there is no way of telling for sure if it is
-valid.
-
-### Known problems
-* It does not check functions recursively so if the pointer is passed to a
-private non-`unsafe` function which does the dereferencing, the lint won't
-trigger.
-* It only checks for arguments whose type are raw pointers, not raw pointers
-got from an argument in some other way (`fn foo(bar: &[*const u8])` or
-`some_argument.get_raw_ptr()`).
-
-### Example
-```
-pub fn foo(x: *const u8) {
-    println!("{}", unsafe { *x });
-}
-```
-
-Use instead:
-```
-pub unsafe fn foo(x: *const u8) {
-    println!("{}", unsafe { *x });
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/obfuscated_if_else.txt b/src/tools/clippy/src/docs/obfuscated_if_else.txt
deleted file mode 100644
index 638f63b0db5..00000000000
--- a/src/tools/clippy/src/docs/obfuscated_if_else.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for usages of `.then_some(..).unwrap_or(..)`
-
-### Why is this bad?
-This can be written more clearly with `if .. else ..`
-
-### Limitations
-This lint currently only looks for usages of
-`.then_some(..).unwrap_or(..)`, but will be expanded
-to account for similar patterns.
-
-### Example
-```
-let x = true;
-x.then_some("a").unwrap_or("b");
-```
-Use instead:
-```
-let x = true;
-if x { "a" } else { "b" };
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/octal_escapes.txt b/src/tools/clippy/src/docs/octal_escapes.txt
deleted file mode 100644
index eee82058715..00000000000
--- a/src/tools/clippy/src/docs/octal_escapes.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-### What it does
-Checks for `\0` escapes in string and byte literals that look like octal
-character escapes in C.
-
-### Why is this bad?
-
-C and other languages support octal character escapes in strings, where
-a backslash is followed by up to three octal digits. For example, `\033`
-stands for the ASCII character 27 (ESC). Rust does not support this
-notation, but has the escape code `\0` which stands for a null
-byte/character, and any following digits do not form part of the escape
-sequence. Therefore, `\033` is not a compiler error but the result may
-be surprising.
-
-### Known problems
-The actual meaning can be the intended one. `\x00` can be used in these
-cases to be unambiguous.
-
-The lint does not trigger for format strings in `print!()`, `write!()`
-and friends since the string is already preprocessed when Clippy lints
-can see it.
-
-### Example
-```
-let one = "\033[1m Bold? \033[0m";  // \033 intended as escape
-let two = "\033\0";                 // \033 intended as null-3-3
-```
-
-Use instead:
-```
-let one = "\x1b[1mWill this be bold?\x1b[0m";
-let two = "\x0033\x00";
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/ok_expect.txt b/src/tools/clippy/src/docs/ok_expect.txt
deleted file mode 100644
index fd5205d49dc..00000000000
--- a/src/tools/clippy/src/docs/ok_expect.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for usage of `ok().expect(..)`.
-
-### Why is this bad?
-Because you usually call `expect()` on the `Result`
-directly to get a better error message.
-
-### Known problems
-The error type needs to implement `Debug`
-
-### Example
-```
-x.ok().expect("why did I do this again?");
-```
-
-Use instead:
-```
-x.expect("why did I do this again?");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/only_used_in_recursion.txt b/src/tools/clippy/src/docs/only_used_in_recursion.txt
deleted file mode 100644
index f19f47ff9eb..00000000000
--- a/src/tools/clippy/src/docs/only_used_in_recursion.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-### What it does
-Checks for arguments that are only used in recursion with no side-effects.
-
-### Why is this bad?
-It could contain a useless calculation and can make function simpler.
-
-The arguments can be involved in calculations and assignments but as long as
-the calculations have no side-effects (function calls or mutating dereference)
-and the assigned variables are also only in recursion, it is useless.
-
-### Known problems
-Too many code paths in the linting code are currently untested and prone to produce false
-positives or are prone to have performance implications.
-
-In some cases, this would not catch all useless arguments.
-
-```
-fn foo(a: usize, b: usize) -> usize {
-    let f = |x| x + 1;
-
-    if a == 0 {
-        1
-    } else {
-        foo(a - 1, f(b))
-    }
-}
-```
-
-For example, the argument `b` is only used in recursion, but the lint would not catch it.
-
-List of some examples that can not be caught:
-- binary operation of non-primitive types
-- closure usage
-- some `break` relative operations
-- struct pattern binding
-
-Also, when you recurse the function name with path segments, it is not possible to detect.
-
-### Example
-```
-fn f(a: usize, b: usize) -> usize {
-    if a == 0 {
-        1
-    } else {
-        f(a - 1, b + 1)
-    }
-}
-```
-Use instead:
-```
-fn f(a: usize) -> usize {
-    if a == 0 {
-        1
-    } else {
-        f(a - 1)
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/op_ref.txt b/src/tools/clippy/src/docs/op_ref.txt
deleted file mode 100644
index 7a7ed1bc9ba..00000000000
--- a/src/tools/clippy/src/docs/op_ref.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for arguments to `==` which have their address
-taken to satisfy a bound
-and suggests to dereference the other argument instead
-
-### Why is this bad?
-It is more idiomatic to dereference the other argument.
-
-### Example
-```
-&x == y
-```
-
-Use instead:
-```
-x == *y
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/option_as_ref_deref.txt b/src/tools/clippy/src/docs/option_as_ref_deref.txt
deleted file mode 100644
index ad7411d3d4b..00000000000
--- a/src/tools/clippy/src/docs/option_as_ref_deref.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for usage of `_.as_ref().map(Deref::deref)` or it's aliases (such as String::as_str).
-
-### Why is this bad?
-Readability, this can be written more concisely as
-`_.as_deref()`.
-
-### Example
-```
-opt.as_ref().map(String::as_str)
-```
-Can be written as
-```
-opt.as_deref()
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/option_env_unwrap.txt b/src/tools/clippy/src/docs/option_env_unwrap.txt
deleted file mode 100644
index c952cba8e26..00000000000
--- a/src/tools/clippy/src/docs/option_env_unwrap.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for usage of `option_env!(...).unwrap()` and
-suggests usage of the `env!` macro.
-
-### Why is this bad?
-Unwrapping the result of `option_env!` will panic
-at run-time if the environment variable doesn't exist, whereas `env!`
-catches it at compile-time.
-
-### Example
-```
-let _ = option_env!("HOME").unwrap();
-```
-
-Is better expressed as:
-
-```
-let _ = env!("HOME");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/option_filter_map.txt b/src/tools/clippy/src/docs/option_filter_map.txt
deleted file mode 100644
index 25f7bde7b4d..00000000000
--- a/src/tools/clippy/src/docs/option_filter_map.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for indirect collection of populated `Option`
-
-### Why is this bad?
-`Option` is like a collection of 0-1 things, so `flatten`
-automatically does this without suspicious-looking `unwrap` calls.
-
-### Example
-```
-let _ = std::iter::empty::<Option<i32>>().filter(Option::is_some).map(Option::unwrap);
-```
-Use instead:
-```
-let _ = std::iter::empty::<Option<i32>>().flatten();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/option_if_let_else.txt b/src/tools/clippy/src/docs/option_if_let_else.txt
deleted file mode 100644
index 43652db513b..00000000000
--- a/src/tools/clippy/src/docs/option_if_let_else.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-### What it does
-Lints usage of `if let Some(v) = ... { y } else { x }` and
-`match .. { Some(v) => y, None/_ => x }` which are more
-idiomatically done with `Option::map_or` (if the else bit is a pure
-expression) or `Option::map_or_else` (if the else bit is an impure
-expression).
-
-### Why is this bad?
-Using the dedicated functions of the `Option` type is clearer and
-more concise than an `if let` expression.
-
-### Known problems
-This lint uses a deliberately conservative metric for checking
-if the inside of either body contains breaks or continues which will
-cause it to not suggest a fix if either block contains a loop with
-continues or breaks contained within the loop.
-
-### Example
-```
-let _ = if let Some(foo) = optional {
-    foo
-} else {
-    5
-};
-let _ = match optional {
-    Some(val) => val + 1,
-    None => 5
-};
-let _ = if let Some(foo) = optional {
-    foo
-} else {
-    let y = do_complicated_function();
-    y*y
-};
-```
-
-should be
-
-```
-let _ = optional.map_or(5, |foo| foo);
-let _ = optional.map_or(5, |val| val + 1);
-let _ = optional.map_or_else(||{
-    let y = do_complicated_function();
-    y*y
-}, |foo| foo);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/option_map_or_none.txt b/src/tools/clippy/src/docs/option_map_or_none.txt
deleted file mode 100644
index c86c65215f0..00000000000
--- a/src/tools/clippy/src/docs/option_map_or_none.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for usage of `_.map_or(None, _)`.
-
-### Why is this bad?
-Readability, this can be written more concisely as
-`_.and_then(_)`.
-
-### Known problems
-The order of the arguments is not in execution order.
-
-### Example
-```
-opt.map_or(None, |a| Some(a + 1));
-```
-
-Use instead:
-```
-opt.and_then(|a| Some(a + 1));
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/option_map_unit_fn.txt b/src/tools/clippy/src/docs/option_map_unit_fn.txt
deleted file mode 100644
index fc4b528f092..00000000000
--- a/src/tools/clippy/src/docs/option_map_unit_fn.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for usage of `option.map(f)` where f is a function
-or closure that returns the unit type `()`.
-
-### Why is this bad?
-Readability, this can be written more clearly with
-an if let statement
-
-### Example
-```
-let x: Option<String> = do_stuff();
-x.map(log_err_msg);
-x.map(|msg| log_err_msg(format_msg(msg)));
-```
-
-The correct use would be:
-
-```
-let x: Option<String> = do_stuff();
-if let Some(msg) = x {
-    log_err_msg(msg);
-}
-
-if let Some(msg) = x {
-    log_err_msg(format_msg(msg));
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/option_option.txt b/src/tools/clippy/src/docs/option_option.txt
deleted file mode 100644
index b4324bd8399..00000000000
--- a/src/tools/clippy/src/docs/option_option.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-### What it does
-Checks for use of `Option<Option<_>>` in function signatures and type
-definitions
-
-### Why is this bad?
-`Option<_>` represents an optional value. `Option<Option<_>>`
-represents an optional optional value which is logically the same thing as an optional
-value but has an unneeded extra level of wrapping.
-
-If you have a case where `Some(Some(_))`, `Some(None)` and `None` are distinct cases,
-consider a custom `enum` instead, with clear names for each case.
-
-### Example
-```
-fn get_data() -> Option<Option<u32>> {
-    None
-}
-```
-
-Better:
-
-```
-pub enum Contents {
-    Data(Vec<u8>), // Was Some(Some(Vec<u8>))
-    NotYetFetched, // Was Some(None)
-    None,          // Was None
-}
-
-fn get_data() -> Contents {
-    Contents::None
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/or_fun_call.txt b/src/tools/clippy/src/docs/or_fun_call.txt
deleted file mode 100644
index 6ce77cc268c..00000000000
--- a/src/tools/clippy/src/docs/or_fun_call.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`,
-`.or_insert(foo(..))` etc., and suggests to use `.or_else(|| foo(..))`,
-`.unwrap_or_else(|| foo(..))`, `.unwrap_or_default()` or `.or_default()`
-etc. instead.
-
-### Why is this bad?
-The function will always be called and potentially
-allocate an object acting as the default.
-
-### Known problems
-If the function has side-effects, not calling it will
-change the semantic of the program, but you shouldn't rely on that anyway.
-
-### Example
-```
-foo.unwrap_or(String::new());
-```
-
-Use instead:
-```
-foo.unwrap_or_else(String::new);
-
-// or
-
-foo.unwrap_or_default();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/or_then_unwrap.txt b/src/tools/clippy/src/docs/or_then_unwrap.txt
deleted file mode 100644
index 64ac53749e8..00000000000
--- a/src/tools/clippy/src/docs/or_then_unwrap.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for `.or(…).unwrap()` calls to Options and Results.
-
-### Why is this bad?
-You should use `.unwrap_or(…)` instead for clarity.
-
-### Example
-```
-// Result
-let value = result.or::<Error>(Ok(fallback)).unwrap();
-
-// Option
-let value = option.or(Some(fallback)).unwrap();
-```
-Use instead:
-```
-// Result
-let value = result.unwrap_or(fallback);
-
-// Option
-let value = option.unwrap_or(fallback);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/out_of_bounds_indexing.txt b/src/tools/clippy/src/docs/out_of_bounds_indexing.txt
deleted file mode 100644
index 5802eea2996..00000000000
--- a/src/tools/clippy/src/docs/out_of_bounds_indexing.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for out of bounds array indexing with a constant
-index.
-
-### Why is this bad?
-This will always panic at runtime.
-
-### Example
-```
-let x = [1, 2, 3, 4];
-
-x[9];
-&x[2..9];
-```
-
-Use instead:
-```
-// Index within bounds
-
-x[0];
-x[3];
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/overflow_check_conditional.txt b/src/tools/clippy/src/docs/overflow_check_conditional.txt
deleted file mode 100644
index a09cc18a0bc..00000000000
--- a/src/tools/clippy/src/docs/overflow_check_conditional.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-### What it does
-Detects classic underflow/overflow checks.
-
-### Why is this bad?
-Most classic C underflow/overflow checks will fail in
-Rust. Users can use functions like `overflowing_*` and `wrapping_*` instead.
-
-### Example
-```
-a + b < a;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/overly_complex_bool_expr.txt b/src/tools/clippy/src/docs/overly_complex_bool_expr.txt
deleted file mode 100644
index 65ca18392e7..00000000000
--- a/src/tools/clippy/src/docs/overly_complex_bool_expr.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for boolean expressions that contain terminals that
-can be eliminated.
-
-### Why is this bad?
-This is most likely a logic bug.
-
-### Known problems
-Ignores short circuiting behavior.
-
-### Example
-```
-// The `b` is unnecessary, the expression is equivalent to `if a`.
-if a && b || a { ... }
-```
-
-Use instead:
-```
-if a {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/panic.txt b/src/tools/clippy/src/docs/panic.txt
deleted file mode 100644
index f9bdc6e87cc..00000000000
--- a/src/tools/clippy/src/docs/panic.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-### What it does
-Checks for usage of `panic!`.
-
-### Why is this bad?
-`panic!` will stop the execution of the executable
-
-### Example
-```
-panic!("even with a good reason");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/panic_in_result_fn.txt b/src/tools/clippy/src/docs/panic_in_result_fn.txt
deleted file mode 100644
index 51c2f8ae5a3..00000000000
--- a/src/tools/clippy/src/docs/panic_in_result_fn.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for usage of `panic!`, `unimplemented!`, `todo!`, `unreachable!` or assertions in a function of type result.
-
-### Why is this bad?
-For some codebases, it is desirable for functions of type result to return an error instead of crashing. Hence panicking macros should be avoided.
-
-### Known problems
-Functions called from a function returning a `Result` may invoke a panicking macro. This is not checked.
-
-### Example
-```
-fn result_with_panic() -> Result<bool, String>
-{
-    panic!("error");
-}
-```
-Use instead:
-```
-fn result_without_panic() -> Result<bool, String> {
-    Err(String::from("error"))
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/panicking_unwrap.txt b/src/tools/clippy/src/docs/panicking_unwrap.txt
deleted file mode 100644
index 1fbc245c8ec..00000000000
--- a/src/tools/clippy/src/docs/panicking_unwrap.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for calls of `unwrap[_err]()` that will always fail.
-
-### Why is this bad?
-If panicking is desired, an explicit `panic!()` should be used.
-
-### Known problems
-This lint only checks `if` conditions not assignments.
-So something like `let x: Option<()> = None; x.unwrap();` will not be recognized.
-
-### Example
-```
-if option.is_none() {
-    do_something_with(option.unwrap())
-}
-```
-
-This code will always panic. The if condition should probably be inverted.
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/partial_pub_fields.txt b/src/tools/clippy/src/docs/partial_pub_fields.txt
deleted file mode 100644
index b529adf1547..00000000000
--- a/src/tools/clippy/src/docs/partial_pub_fields.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks whether partial fields of a struct are public.
-
-Either make all fields of a type public, or make none of them public
-
-### Why is this bad?
-Most types should either be:
-* Abstract data types: complex objects with opaque implementation which guard
-interior invariants and expose intentionally limited API to the outside world.
-* Data: relatively simple objects which group a bunch of related attributes together.
-
-### Example
-```
-pub struct Color {
-    pub r: u8,
-    pub g: u8,
-    b: u8,
-}
-```
-Use instead:
-```
-pub struct Color {
-    pub r: u8,
-    pub g: u8,
-    pub b: u8,
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/partialeq_ne_impl.txt b/src/tools/clippy/src/docs/partialeq_ne_impl.txt
deleted file mode 100644
index 78f55188bab..00000000000
--- a/src/tools/clippy/src/docs/partialeq_ne_impl.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for manual re-implementations of `PartialEq::ne`.
-
-### Why is this bad?
-`PartialEq::ne` is required to always return the
-negated result of `PartialEq::eq`, which is exactly what the default
-implementation does. Therefore, there should never be any need to
-re-implement it.
-
-### Example
-```
-struct Foo;
-
-impl PartialEq for Foo {
-   fn eq(&self, other: &Foo) -> bool { true }
-   fn ne(&self, other: &Foo) -> bool { !(self == other) }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/partialeq_to_none.txt b/src/tools/clippy/src/docs/partialeq_to_none.txt
deleted file mode 100644
index 5cc07bf8843..00000000000
--- a/src/tools/clippy/src/docs/partialeq_to_none.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-
-Checks for binary comparisons to a literal `Option::None`.
-
-### Why is this bad?
-
-A programmer checking if some `foo` is `None` via a comparison `foo == None`
-is usually inspired from other programming languages (e.g. `foo is None`
-in Python).
-Checking if a value of type `Option<T>` is (not) equal to `None` in that
-way relies on `T: PartialEq` to do the comparison, which is unneeded.
-
-### Example
-```
-fn foo(f: Option<u32>) -> &'static str {
-    if f != None { "yay" } else { "nay" }
-}
-```
-Use instead:
-```
-fn foo(f: Option<u32>) -> &'static str {
-    if f.is_some() { "yay" } else { "nay" }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/path_buf_push_overwrite.txt b/src/tools/clippy/src/docs/path_buf_push_overwrite.txt
deleted file mode 100644
index 34f8901da23..00000000000
--- a/src/tools/clippy/src/docs/path_buf_push_overwrite.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-* Checks for [push](https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.push)
-calls on `PathBuf` that can cause overwrites.
-
-### Why is this bad?
-Calling `push` with a root path at the start can overwrite the
-previous defined path.
-
-### Example
-```
-use std::path::PathBuf;
-
-let mut x = PathBuf::from("/foo");
-x.push("/bar");
-assert_eq!(x, PathBuf::from("/bar"));
-```
-Could be written:
-
-```
-use std::path::PathBuf;
-
-let mut x = PathBuf::from("/foo");
-x.push("bar");
-assert_eq!(x, PathBuf::from("/foo/bar"));
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/pattern_type_mismatch.txt b/src/tools/clippy/src/docs/pattern_type_mismatch.txt
deleted file mode 100644
index 64da881d592..00000000000
--- a/src/tools/clippy/src/docs/pattern_type_mismatch.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-### What it does
-Checks for patterns that aren't exact representations of the types
-they are applied to.
-
-To satisfy this lint, you will have to adjust either the expression that is matched
-against or the pattern itself, as well as the bindings that are introduced by the
-adjusted patterns. For matching you will have to either dereference the expression
-with the `*` operator, or amend the patterns to explicitly match against `&<pattern>`
-or `&mut <pattern>` depending on the reference mutability. For the bindings you need
-to use the inverse. You can leave them as plain bindings if you wish for the value
-to be copied, but you must use `ref mut <variable>` or `ref <variable>` to construct
-a reference into the matched structure.
-
-If you are looking for a way to learn about ownership semantics in more detail, it
-is recommended to look at IDE options available to you to highlight types, lifetimes
-and reference semantics in your code. The available tooling would expose these things
-in a general way even outside of the various pattern matching mechanics. Of course
-this lint can still be used to highlight areas of interest and ensure a good understanding
-of ownership semantics.
-
-### Why is this bad?
-It isn't bad in general. But in some contexts it can be desirable
-because it increases ownership hints in the code, and will guard against some changes
-in ownership.
-
-### Example
-This example shows the basic adjustments necessary to satisfy the lint. Note how
-the matched expression is explicitly dereferenced with `*` and the `inner` variable
-is bound to a shared borrow via `ref inner`.
-
-```
-// Bad
-let value = &Some(Box::new(23));
-match value {
-    Some(inner) => println!("{}", inner),
-    None => println!("none"),
-}
-
-// Good
-let value = &Some(Box::new(23));
-match *value {
-    Some(ref inner) => println!("{}", inner),
-    None => println!("none"),
-}
-```
-
-The following example demonstrates one of the advantages of the more verbose style.
-Note how the second version uses `ref mut a` to explicitly declare `a` a shared mutable
-borrow, while `b` is simply taken by value. This ensures that the loop body cannot
-accidentally modify the wrong part of the structure.
-
-```
-// Bad
-let mut values = vec![(2, 3), (3, 4)];
-for (a, b) in &mut values {
-    *a += *b;
-}
-
-// Good
-let mut values = vec![(2, 3), (3, 4)];
-for &mut (ref mut a, b) in &mut values {
-    *a += b;
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/possible_missing_comma.txt b/src/tools/clippy/src/docs/possible_missing_comma.txt
deleted file mode 100644
index 5d92f4cae91..00000000000
--- a/src/tools/clippy/src/docs/possible_missing_comma.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Checks for possible missing comma in an array. It lints if
-an array element is a binary operator expression and it lies on two lines.
-
-### Why is this bad?
-This could lead to unexpected results.
-
-### Example
-```
-let a = &[
-    -1, -2, -3 // <= no comma here
-    -4, -5, -6
-];
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/precedence.txt b/src/tools/clippy/src/docs/precedence.txt
deleted file mode 100644
index fda0b831f33..00000000000
--- a/src/tools/clippy/src/docs/precedence.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for operations where precedence may be unclear
-and suggests to add parentheses. Currently it catches the following:
-* mixed usage of arithmetic and bit shifting/combining operators without
-parentheses
-* a "negative" numeric literal (which is really a unary `-` followed by a
-numeric literal)
-  followed by a method call
-
-### Why is this bad?
-Not everyone knows the precedence of those operators by
-heart, so expressions like these may trip others trying to reason about the
-code.
-
-### Example
-* `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7
-* `-1i32.abs()` equals -1, while `(-1i32).abs()` equals 1
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/print_in_format_impl.txt b/src/tools/clippy/src/docs/print_in_format_impl.txt
deleted file mode 100644
index 140d23d6faa..00000000000
--- a/src/tools/clippy/src/docs/print_in_format_impl.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-### What it does
-Checks for use of `println`, `print`, `eprintln` or `eprint` in an
-implementation of a formatting trait.
-
-### Why is this bad?
-Using a print macro is likely unintentional since formatting traits
-should write to the `Formatter`, not stdout/stderr.
-
-### Example
-```
-use std::fmt::{Display, Error, Formatter};
-
-struct S;
-impl Display for S {
-    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
-        println!("S");
-
-        Ok(())
-    }
-}
-```
-Use instead:
-```
-use std::fmt::{Display, Error, Formatter};
-
-struct S;
-impl Display for S {
-    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
-        writeln!(f, "S");
-
-        Ok(())
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/print_literal.txt b/src/tools/clippy/src/docs/print_literal.txt
deleted file mode 100644
index a6252a68780..00000000000
--- a/src/tools/clippy/src/docs/print_literal.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-This lint warns about the use of literals as `print!`/`println!` args.
-
-### Why is this bad?
-Using literals as `println!` args is inefficient
-(c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
-(i.e., just put the literal in the format string)
-
-### Example
-```
-println!("{}", "foo");
-```
-use the literal without formatting:
-```
-println!("foo");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/print_stderr.txt b/src/tools/clippy/src/docs/print_stderr.txt
deleted file mode 100644
index 9c6edeeef12..00000000000
--- a/src/tools/clippy/src/docs/print_stderr.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for printing on *stderr*. The purpose of this lint
-is to catch debugging remnants.
-
-### Why is this bad?
-People often print on *stderr* while debugging an
-application and might forget to remove those prints afterward.
-
-### Known problems
-Only catches `eprint!` and `eprintln!` calls.
-
-### Example
-```
-eprintln!("Hello world!");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/print_stdout.txt b/src/tools/clippy/src/docs/print_stdout.txt
deleted file mode 100644
index d2cbd811d1b..00000000000
--- a/src/tools/clippy/src/docs/print_stdout.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for printing on *stdout*. The purpose of this lint
-is to catch debugging remnants.
-
-### Why is this bad?
-People often print on *stdout* while debugging an
-application and might forget to remove those prints afterward.
-
-### Known problems
-Only catches `print!` and `println!` calls.
-
-### Example
-```
-println!("Hello world!");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/print_with_newline.txt b/src/tools/clippy/src/docs/print_with_newline.txt
deleted file mode 100644
index 640323e822d..00000000000
--- a/src/tools/clippy/src/docs/print_with_newline.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-This lint warns when you use `print!()` with a format
-string that ends in a newline.
-
-### Why is this bad?
-You should use `println!()` instead, which appends the
-newline.
-
-### Example
-```
-print!("Hello {}!\n", name);
-```
-use println!() instead
-```
-println!("Hello {}!", name);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/println_empty_string.txt b/src/tools/clippy/src/docs/println_empty_string.txt
deleted file mode 100644
index b980413022c..00000000000
--- a/src/tools/clippy/src/docs/println_empty_string.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-This lint warns when you use `println!("")` to
-print a newline.
-
-### Why is this bad?
-You should use `println!()`, which is simpler.
-
-### Example
-```
-println!("");
-```
-
-Use instead:
-```
-println!();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/ptr_arg.txt b/src/tools/clippy/src/docs/ptr_arg.txt
deleted file mode 100644
index 796b0a65b71..00000000000
--- a/src/tools/clippy/src/docs/ptr_arg.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-This lint checks for function arguments of type `&String`, `&Vec`,
-`&PathBuf`, and `Cow<_>`. It will also suggest you replace `.clone()` calls
-with the appropriate `.to_owned()`/`to_string()` calls.
-
-### Why is this bad?
-Requiring the argument to be of the specific size
-makes the function less useful for no benefit; slices in the form of `&[T]`
-or `&str` usually suffice and can be obtained from other types, too.
-
-### Known problems
-There may be `fn(&Vec)`-typed references pointing to your function.
-If you have them, you will get a compiler error after applying this lint's
-suggestions. You then have the choice to undo your changes or change the
-type of the reference.
-
-Note that if the function is part of your public interface, there may be
-other crates referencing it, of which you may not be aware. Carefully
-deprecate the function before applying the lint suggestions in this case.
-
-### Example
-```
-fn foo(&Vec<u32>) { .. }
-```
-
-Use instead:
-```
-fn foo(&[u32]) { .. }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/ptr_as_ptr.txt b/src/tools/clippy/src/docs/ptr_as_ptr.txt
deleted file mode 100644
index 8fb35c4aae8..00000000000
--- a/src/tools/clippy/src/docs/ptr_as_ptr.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for `as` casts between raw pointers without changing its mutability,
-namely `*const T` to `*const U` and `*mut T` to `*mut U`.
-
-### Why is this bad?
-Though `as` casts between raw pointers is not terrible, `pointer::cast` is safer because
-it cannot accidentally change the pointer's mutability nor cast the pointer to other types like `usize`.
-
-### Example
-```
-let ptr: *const u32 = &42_u32;
-let mut_ptr: *mut u32 = &mut 42_u32;
-let _ = ptr as *const i32;
-let _ = mut_ptr as *mut i32;
-```
-Use instead:
-```
-let ptr: *const u32 = &42_u32;
-let mut_ptr: *mut u32 = &mut 42_u32;
-let _ = ptr.cast::<i32>();
-let _ = mut_ptr.cast::<i32>();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/ptr_eq.txt b/src/tools/clippy/src/docs/ptr_eq.txt
deleted file mode 100644
index 06b36ca55e6..00000000000
--- a/src/tools/clippy/src/docs/ptr_eq.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Use `std::ptr::eq` when applicable
-
-### Why is this bad?
-`ptr::eq` can be used to compare `&T` references
-(which coerce to `*const T` implicitly) by their address rather than
-comparing the values they point to.
-
-### Example
-```
-let a = &[1, 2, 3];
-let b = &[1, 2, 3];
-
-assert!(a as *const _ as usize == b as *const _ as usize);
-```
-Use instead:
-```
-let a = &[1, 2, 3];
-let b = &[1, 2, 3];
-
-assert!(std::ptr::eq(a, b));
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/ptr_offset_with_cast.txt b/src/tools/clippy/src/docs/ptr_offset_with_cast.txt
deleted file mode 100644
index f204e769bf4..00000000000
--- a/src/tools/clippy/src/docs/ptr_offset_with_cast.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-### What it does
-Checks for usage of the `offset` pointer method with a `usize` casted to an
-`isize`.
-
-### Why is this bad?
-If we’re always increasing the pointer address, we can avoid the numeric
-cast by using the `add` method instead.
-
-### Example
-```
-let vec = vec![b'a', b'b', b'c'];
-let ptr = vec.as_ptr();
-let offset = 1_usize;
-
-unsafe {
-    ptr.offset(offset as isize);
-}
-```
-
-Could be written:
-
-```
-let vec = vec![b'a', b'b', b'c'];
-let ptr = vec.as_ptr();
-let offset = 1_usize;
-
-unsafe {
-    ptr.add(offset);
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/pub_use.txt b/src/tools/clippy/src/docs/pub_use.txt
deleted file mode 100644
index 407cafa0190..00000000000
--- a/src/tools/clippy/src/docs/pub_use.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-### What it does
-
-Restricts the usage of `pub use ...`
-
-### Why is this bad?
-
-`pub use` is usually fine, but a project may wish to limit `pub use` instances to prevent
-unintentional exports or to encourage placing exported items directly in public modules
-
-### Example
-```
-pub mod outer {
-    mod inner {
-        pub struct Test {}
-    }
-    pub use inner::Test;
-}
-
-use outer::Test;
-```
-Use instead:
-```
-pub mod outer {
-    pub struct Test {}
-}
-
-use outer::Test;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/question_mark.txt b/src/tools/clippy/src/docs/question_mark.txt
deleted file mode 100644
index 4dc987be881..00000000000
--- a/src/tools/clippy/src/docs/question_mark.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for expressions that could be replaced by the question mark operator.
-
-### Why is this bad?
-Question mark usage is more idiomatic.
-
-### Example
-```
-if option.is_none() {
-    return None;
-}
-```
-
-Could be written:
-
-```
-option?;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/range_minus_one.txt b/src/tools/clippy/src/docs/range_minus_one.txt
deleted file mode 100644
index fcb96dcc34e..00000000000
--- a/src/tools/clippy/src/docs/range_minus_one.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for inclusive ranges where 1 is subtracted from
-the upper bound, e.g., `x..=(y-1)`.
-
-### Why is this bad?
-The code is more readable with an exclusive range
-like `x..y`.
-
-### Known problems
-This will cause a warning that cannot be fixed if
-the consumer of the range only accepts a specific range type, instead of
-the generic `RangeBounds` trait
-([#3307](https://github.com/rust-lang/rust-clippy/issues/3307)).
-
-### Example
-```
-for i in x..=(y-1) {
-    // ..
-}
-```
-
-Use instead:
-```
-for i in x..y {
-    // ..
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/range_plus_one.txt b/src/tools/clippy/src/docs/range_plus_one.txt
deleted file mode 100644
index 193c85f9cbc..00000000000
--- a/src/tools/clippy/src/docs/range_plus_one.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-### What it does
-Checks for exclusive ranges where 1 is added to the
-upper bound, e.g., `x..(y+1)`.
-
-### Why is this bad?
-The code is more readable with an inclusive range
-like `x..=y`.
-
-### Known problems
-Will add unnecessary pair of parentheses when the
-expression is not wrapped in a pair but starts with an opening parenthesis
-and ends with a closing one.
-I.e., `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..=f())`.
-
-Also in many cases, inclusive ranges are still slower to run than
-exclusive ranges, because they essentially add an extra branch that
-LLVM may fail to hoist out of the loop.
-
-This will cause a warning that cannot be fixed if the consumer of the
-range only accepts a specific range type, instead of the generic
-`RangeBounds` trait
-([#3307](https://github.com/rust-lang/rust-clippy/issues/3307)).
-
-### Example
-```
-for i in x..(y+1) {
-    // ..
-}
-```
-
-Use instead:
-```
-for i in x..=y {
-    // ..
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/range_zip_with_len.txt b/src/tools/clippy/src/docs/range_zip_with_len.txt
deleted file mode 100644
index 24c1efec789..00000000000
--- a/src/tools/clippy/src/docs/range_zip_with_len.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for zipping a collection with the range of
-`0.._.len()`.
-
-### Why is this bad?
-The code is better expressed with `.enumerate()`.
-
-### Example
-```
-let _ = x.iter().zip(0..x.len());
-```
-
-Use instead:
-```
-let _ = x.iter().enumerate();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/rc_buffer.txt b/src/tools/clippy/src/docs/rc_buffer.txt
deleted file mode 100644
index 82ac58eeb30..00000000000
--- a/src/tools/clippy/src/docs/rc_buffer.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for `Rc<T>` and `Arc<T>` when `T` is a mutable buffer type such as `String` or `Vec`.
-
-### Why is this bad?
-Expressions such as `Rc<String>` usually have no advantage over `Rc<str>`, since
-it is larger and involves an extra level of indirection, and doesn't implement `Borrow<str>`.
-
-While mutating a buffer type would still be possible with `Rc::get_mut()`, it only
-works if there are no additional references yet, which usually defeats the purpose of
-enclosing it in a shared ownership type. Instead, additionally wrapping the inner
-type with an interior mutable container (such as `RefCell` or `Mutex`) would normally
-be used.
-
-### Known problems
-This pattern can be desirable to avoid the overhead of a `RefCell` or `Mutex` for
-cases where mutation only happens before there are any additional references.
-
-### Example
-```
-fn foo(interned: Rc<String>) { ... }
-```
-
-Better:
-
-```
-fn foo(interned: Rc<str>) { ... }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/rc_clone_in_vec_init.txt b/src/tools/clippy/src/docs/rc_clone_in_vec_init.txt
deleted file mode 100644
index 6fc08aaf9ab..00000000000
--- a/src/tools/clippy/src/docs/rc_clone_in_vec_init.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Checks for reference-counted pointers (`Arc`, `Rc`, `rc::Weak`, and `sync::Weak`)
-in `vec![elem; len]`
-
-### Why is this bad?
-This will create `elem` once and clone it `len` times - doing so with `Arc`/`Rc`/`Weak`
-is a bit misleading, as it will create references to the same pointer, rather
-than different instances.
-
-### Example
-```
-let v = vec![std::sync::Arc::new("some data".to_string()); 100];
-// or
-let v = vec![std::rc::Rc::new("some data".to_string()); 100];
-```
-Use instead:
-```
-// Initialize each value separately:
-let mut data = Vec::with_capacity(100);
-for _ in 0..100 {
-    data.push(std::rc::Rc::new("some data".to_string()));
-}
-
-// Or if you want clones of the same reference,
-// Create the reference beforehand to clarify that
-// it should be cloned for each value
-let data = std::rc::Rc::new("some data".to_string());
-let v = vec![data; 100];
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/rc_mutex.txt b/src/tools/clippy/src/docs/rc_mutex.txt
deleted file mode 100644
index ed7a1e344d0..00000000000
--- a/src/tools/clippy/src/docs/rc_mutex.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for `Rc<Mutex<T>>`.
-
-### Why is this bad?
-`Rc` is used in single thread and `Mutex` is used in multi thread.
-Consider using `Rc<RefCell<T>>` in single thread or `Arc<Mutex<T>>` in multi thread.
-
-### Known problems
-Sometimes combining generic types can lead to the requirement that a
-type use Rc in conjunction with Mutex. We must consider those cases false positives, but
-alas they are quite hard to rule out. Luckily they are also rare.
-
-### Example
-```
-use std::rc::Rc;
-use std::sync::Mutex;
-fn foo(interned: Rc<Mutex<i32>>) { ... }
-```
-
-Better:
-
-```
-use std::rc::Rc;
-use std::cell::RefCell
-fn foo(interned: Rc<RefCell<i32>>) { ... }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/read_zero_byte_vec.txt b/src/tools/clippy/src/docs/read_zero_byte_vec.txt
deleted file mode 100644
index cef5604e01c..00000000000
--- a/src/tools/clippy/src/docs/read_zero_byte_vec.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-### What it does
-This lint catches reads into a zero-length `Vec`.
-Especially in the case of a call to `with_capacity`, this lint warns that read
-gets the number of bytes from the `Vec`'s length, not its capacity.
-
-### Why is this bad?
-Reading zero bytes is almost certainly not the intended behavior.
-
-### Known problems
-In theory, a very unusual read implementation could assign some semantic meaning
-to zero-byte reads. But it seems exceptionally unlikely that code intending to do
-a zero-byte read would allocate a `Vec` for it.
-
-### Example
-```
-use std::io;
-fn foo<F: io::Read>(mut f: F) {
-    let mut data = Vec::with_capacity(100);
-    f.read(&mut data).unwrap();
-}
-```
-Use instead:
-```
-use std::io;
-fn foo<F: io::Read>(mut f: F) {
-    let mut data = Vec::with_capacity(100);
-    data.resize(100, 0);
-    f.read(&mut data).unwrap();
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/recursive_format_impl.txt b/src/tools/clippy/src/docs/recursive_format_impl.txt
deleted file mode 100644
index 32fffd84cf4..00000000000
--- a/src/tools/clippy/src/docs/recursive_format_impl.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-### What it does
-Checks for format trait implementations (e.g. `Display`) with a recursive call to itself
-which uses `self` as a parameter.
-This is typically done indirectly with the `write!` macro or with `to_string()`.
-
-### Why is this bad?
-This will lead to infinite recursion and a stack overflow.
-
-### Example
-
-```
-use std::fmt;
-
-struct Structure(i32);
-impl fmt::Display for Structure {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.to_string())
-    }
-}
-
-```
-Use instead:
-```
-use std::fmt;
-
-struct Structure(i32);
-impl fmt::Display for Structure {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.0)
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/redundant_allocation.txt b/src/tools/clippy/src/docs/redundant_allocation.txt
deleted file mode 100644
index 86bf51e8dfe..00000000000
--- a/src/tools/clippy/src/docs/redundant_allocation.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for use of redundant allocations anywhere in the code.
-
-### Why is this bad?
-Expressions such as `Rc<&T>`, `Rc<Rc<T>>`, `Rc<Arc<T>>`, `Rc<Box<T>>`, `Arc<&T>`, `Arc<Rc<T>>`,
-`Arc<Arc<T>>`, `Arc<Box<T>>`, `Box<&T>`, `Box<Rc<T>>`, `Box<Arc<T>>`, `Box<Box<T>>`, add an unnecessary level of indirection.
-
-### Example
-```
-fn foo(bar: Rc<&usize>) {}
-```
-
-Better:
-
-```
-fn foo(bar: &usize) {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/redundant_clone.txt b/src/tools/clippy/src/docs/redundant_clone.txt
deleted file mode 100644
index b29aed0b5e7..00000000000
--- a/src/tools/clippy/src/docs/redundant_clone.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for a redundant `clone()` (and its relatives) which clones an owned
-value that is going to be dropped without further use.
-
-### Why is this bad?
-It is not always possible for the compiler to eliminate useless
-allocations and deallocations generated by redundant `clone()`s.
-
-### Known problems
-False-negatives: analysis performed by this lint is conservative and limited.
-
-### Example
-```
-{
-    let x = Foo::new();
-    call(x.clone());
-    call(x.clone()); // this can just pass `x`
-}
-
-["lorem", "ipsum"].join(" ").to_string();
-
-Path::new("/a/b").join("c").to_path_buf();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/redundant_closure.txt b/src/tools/clippy/src/docs/redundant_closure.txt
deleted file mode 100644
index 0faa9513f97..00000000000
--- a/src/tools/clippy/src/docs/redundant_closure.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Checks for closures which just call another function where
-the function can be called directly. `unsafe` functions or calls where types
-get adjusted are ignored.
-
-### Why is this bad?
-Needlessly creating a closure adds code for no benefit
-and gives the optimizer more work.
-
-### Known problems
-If creating the closure inside the closure has a side-
-effect then moving the closure creation out will change when that side-
-effect runs.
-See [#1439](https://github.com/rust-lang/rust-clippy/issues/1439) for more details.
-
-### Example
-```
-xs.map(|x| foo(x))
-```
-
-Use instead:
-```
-// where `foo(_)` is a plain function that takes the exact argument type of `x`.
-xs.map(foo)
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/redundant_closure_call.txt b/src/tools/clippy/src/docs/redundant_closure_call.txt
deleted file mode 100644
index 913d1a705e2..00000000000
--- a/src/tools/clippy/src/docs/redundant_closure_call.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Detects closures called in the same expression where they
-are defined.
-
-### Why is this bad?
-It is unnecessarily adding to the expression's
-complexity.
-
-### Example
-```
-let a = (|| 42)();
-```
-
-Use instead:
-```
-let a = 42;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/redundant_closure_for_method_calls.txt b/src/tools/clippy/src/docs/redundant_closure_for_method_calls.txt
deleted file mode 100644
index 865510e1475..00000000000
--- a/src/tools/clippy/src/docs/redundant_closure_for_method_calls.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for closures which only invoke a method on the closure
-argument and can be replaced by referencing the method directly.
-
-### Why is this bad?
-It's unnecessary to create the closure.
-
-### Example
-```
-Some('a').map(|s| s.to_uppercase());
-```
-may be rewritten as
-```
-Some('a').map(char::to_uppercase);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/redundant_else.txt b/src/tools/clippy/src/docs/redundant_else.txt
deleted file mode 100644
index 3f4e8691760..00000000000
--- a/src/tools/clippy/src/docs/redundant_else.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-### What it does
-Checks for `else` blocks that can be removed without changing semantics.
-
-### Why is this bad?
-The `else` block adds unnecessary indentation and verbosity.
-
-### Known problems
-Some may prefer to keep the `else` block for clarity.
-
-### Example
-```
-fn my_func(count: u32) {
-    if count == 0 {
-        print!("Nothing to do");
-        return;
-    } else {
-        print!("Moving on...");
-    }
-}
-```
-Use instead:
-```
-fn my_func(count: u32) {
-    if count == 0 {
-        print!("Nothing to do");
-        return;
-    }
-    print!("Moving on...");
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/redundant_feature_names.txt b/src/tools/clippy/src/docs/redundant_feature_names.txt
deleted file mode 100644
index 5bd6925ed47..00000000000
--- a/src/tools/clippy/src/docs/redundant_feature_names.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for feature names with prefix `use-`, `with-` or suffix `-support`
-
-### Why is this bad?
-These prefixes and suffixes have no significant meaning.
-
-### Example
-```
-[features]
-default = ["use-abc", "with-def", "ghi-support"]
-use-abc = []  // redundant
-with-def = []   // redundant
-ghi-support = []   // redundant
-```
-
-Use instead:
-```
-[features]
-default = ["abc", "def", "ghi"]
-abc = []
-def = []
-ghi = []
-```
diff --git a/src/tools/clippy/src/docs/redundant_field_names.txt b/src/tools/clippy/src/docs/redundant_field_names.txt
deleted file mode 100644
index 35f20a466b3..00000000000
--- a/src/tools/clippy/src/docs/redundant_field_names.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for fields in struct literals where shorthands
-could be used.
-
-### Why is this bad?
-If the field and variable names are the same,
-the field name is redundant.
-
-### Example
-```
-let bar: u8 = 123;
-
-struct Foo {
-    bar: u8,
-}
-
-let foo = Foo { bar: bar };
-```
-the last line can be simplified to
-```
-let foo = Foo { bar };
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/redundant_pattern.txt b/src/tools/clippy/src/docs/redundant_pattern.txt
deleted file mode 100644
index 45f6cfc8670..00000000000
--- a/src/tools/clippy/src/docs/redundant_pattern.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for patterns in the form `name @ _`.
-
-### Why is this bad?
-It's almost always more readable to just use direct
-bindings.
-
-### Example
-```
-match v {
-    Some(x) => (),
-    y @ _ => (),
-}
-```
-
-Use instead:
-```
-match v {
-    Some(x) => (),
-    y => (),
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/redundant_pattern_matching.txt b/src/tools/clippy/src/docs/redundant_pattern_matching.txt
deleted file mode 100644
index 77b1021e0db..00000000000
--- a/src/tools/clippy/src/docs/redundant_pattern_matching.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-### What it does
-Lint for redundant pattern matching over `Result`, `Option`,
-`std::task::Poll` or `std::net::IpAddr`
-
-### Why is this bad?
-It's more concise and clear to just use the proper
-utility function
-
-### Known problems
-This will change the drop order for the matched type. Both `if let` and
-`while let` will drop the value at the end of the block, both `if` and `while` will drop the
-value before entering the block. For most types this change will not matter, but for a few
-types this will not be an acceptable change (e.g. locks). See the
-[reference](https://doc.rust-lang.org/reference/destructors.html#drop-scopes) for more about
-drop order.
-
-### Example
-```
-if let Ok(_) = Ok::<i32, i32>(42) {}
-if let Err(_) = Err::<i32, i32>(42) {}
-if let None = None::<()> {}
-if let Some(_) = Some(42) {}
-if let Poll::Pending = Poll::Pending::<()> {}
-if let Poll::Ready(_) = Poll::Ready(42) {}
-if let IpAddr::V4(_) = IpAddr::V4(Ipv4Addr::LOCALHOST) {}
-if let IpAddr::V6(_) = IpAddr::V6(Ipv6Addr::LOCALHOST) {}
-match Ok::<i32, i32>(42) {
-    Ok(_) => true,
-    Err(_) => false,
-};
-```
-
-The more idiomatic use would be:
-
-```
-if Ok::<i32, i32>(42).is_ok() {}
-if Err::<i32, i32>(42).is_err() {}
-if None::<()>.is_none() {}
-if Some(42).is_some() {}
-if Poll::Pending::<()>.is_pending() {}
-if Poll::Ready(42).is_ready() {}
-if IpAddr::V4(Ipv4Addr::LOCALHOST).is_ipv4() {}
-if IpAddr::V6(Ipv6Addr::LOCALHOST).is_ipv6() {}
-Ok::<i32, i32>(42).is_ok();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/redundant_pub_crate.txt b/src/tools/clippy/src/docs/redundant_pub_crate.txt
deleted file mode 100644
index a527bb5acda..00000000000
--- a/src/tools/clippy/src/docs/redundant_pub_crate.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for items declared `pub(crate)` that are not crate visible because they
-are inside a private module.
-
-### Why is this bad?
-Writing `pub(crate)` is misleading when it's redundant due to the parent
-module's visibility.
-
-### Example
-```
-mod internal {
-    pub(crate) fn internal_fn() { }
-}
-```
-This function is not visible outside the module and it can be declared with `pub` or
-private visibility
-```
-mod internal {
-    pub fn internal_fn() { }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/redundant_slicing.txt b/src/tools/clippy/src/docs/redundant_slicing.txt
deleted file mode 100644
index 6798911ed76..00000000000
--- a/src/tools/clippy/src/docs/redundant_slicing.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for redundant slicing expressions which use the full range, and
-do not change the type.
-
-### Why is this bad?
-It unnecessarily adds complexity to the expression.
-
-### Known problems
-If the type being sliced has an implementation of `Index<RangeFull>`
-that actually changes anything then it can't be removed. However, this would be surprising
-to people reading the code and should have a note with it.
-
-### Example
-```
-fn get_slice(x: &[u32]) -> &[u32] {
-    &x[..]
-}
-```
-Use instead:
-```
-fn get_slice(x: &[u32]) -> &[u32] {
-    x
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/redundant_static_lifetimes.txt b/src/tools/clippy/src/docs/redundant_static_lifetimes.txt
deleted file mode 100644
index edb8e7b5c62..00000000000
--- a/src/tools/clippy/src/docs/redundant_static_lifetimes.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for constants and statics with an explicit `'static` lifetime.
-
-### Why is this bad?
-Adding `'static` to every reference can create very
-complicated types.
-
-### Example
-```
-const FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] =
-&[...]
-static FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] =
-&[...]
-```
-This code can be rewritten as
-```
- const FOO: &[(&str, &str, fn(&Bar) -> bool)] = &[...]
- static FOO: &[(&str, &str, fn(&Bar) -> bool)] = &[...]
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/ref_binding_to_reference.txt b/src/tools/clippy/src/docs/ref_binding_to_reference.txt
deleted file mode 100644
index dc391cd988e..00000000000
--- a/src/tools/clippy/src/docs/ref_binding_to_reference.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for `ref` bindings which create a reference to a reference.
-
-### Why is this bad?
-The address-of operator at the use site is clearer about the need for a reference.
-
-### Example
-```
-let x = Some("");
-if let Some(ref x) = x {
-    // use `x` here
-}
-```
-
-Use instead:
-```
-let x = Some("");
-if let Some(x) = x {
-    // use `&x` here
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/ref_option_ref.txt b/src/tools/clippy/src/docs/ref_option_ref.txt
deleted file mode 100644
index 951c7bd7f7e..00000000000
--- a/src/tools/clippy/src/docs/ref_option_ref.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for usage of `&Option<&T>`.
-
-### Why is this bad?
-Since `&` is Copy, it's useless to have a
-reference on `Option<&T>`.
-
-### Known problems
-It may be irrelevant to use this lint on
-public API code as it will make a breaking change to apply it.
-
-### Example
-```
-let x: &Option<&u32> = &Some(&0u32);
-```
-Use instead:
-```
-let x: Option<&u32> = Some(&0u32);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/repeat_once.txt b/src/tools/clippy/src/docs/repeat_once.txt
deleted file mode 100644
index 3ba189c1945..00000000000
--- a/src/tools/clippy/src/docs/repeat_once.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Checks for usage of `.repeat(1)` and suggest the following method for each types.
-- `.to_string()` for `str`
-- `.clone()` for `String`
-- `.to_vec()` for `slice`
-
-The lint will evaluate constant expressions and values as arguments of `.repeat(..)` and emit a message if
-they are equivalent to `1`. (Related discussion in [rust-clippy#7306](https://github.com/rust-lang/rust-clippy/issues/7306))
-
-### Why is this bad?
-For example, `String.repeat(1)` is equivalent to `.clone()`. If cloning
-the string is the intention behind this, `clone()` should be used.
-
-### Example
-```
-fn main() {
-    let x = String::from("hello world").repeat(1);
-}
-```
-Use instead:
-```
-fn main() {
-    let x = String::from("hello world").clone();
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/rest_pat_in_fully_bound_structs.txt b/src/tools/clippy/src/docs/rest_pat_in_fully_bound_structs.txt
deleted file mode 100644
index 40ebbe754a3..00000000000
--- a/src/tools/clippy/src/docs/rest_pat_in_fully_bound_structs.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for unnecessary '..' pattern binding on struct when all fields are explicitly matched.
-
-### Why is this bad?
-Correctness and readability. It's like having a wildcard pattern after
-matching all enum variants explicitly.
-
-### Example
-```
-let a = A { a: 5 };
-
-match a {
-    A { a: 5, .. } => {},
-    _ => {},
-}
-```
-
-Use instead:
-```
-match a {
-    A { a: 5 } => {},
-    _ => {},
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/result_large_err.txt b/src/tools/clippy/src/docs/result_large_err.txt
deleted file mode 100644
index e5fab3c5cfc..00000000000
--- a/src/tools/clippy/src/docs/result_large_err.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-### What it does
-Checks for functions that return `Result` with an unusually large
-`Err`-variant.
-
-### Why is this bad?
-A `Result` is at least as large as the `Err`-variant. While we
-expect that variant to be seldomly used, the compiler needs to reserve
-and move that much memory every single time.
-
-### Known problems
-The size determined by Clippy is platform-dependent.
-
-### Examples
-```
-pub enum ParseError {
-    UnparsedBytes([u8; 512]),
-    UnexpectedEof,
-}
-
-// The `Result` has at least 512 bytes, even in the `Ok`-case
-pub fn parse() -> Result<(), ParseError> {
-    Ok(())
-}
-```
-should be
-```
-pub enum ParseError {
-    UnparsedBytes(Box<[u8; 512]>),
-    UnexpectedEof,
-}
-
-// The `Result` is slightly larger than a pointer
-pub fn parse() -> Result<(), ParseError> {
-    Ok(())
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/result_map_or_into_option.txt b/src/tools/clippy/src/docs/result_map_or_into_option.txt
deleted file mode 100644
index 899d98c307c..00000000000
--- a/src/tools/clippy/src/docs/result_map_or_into_option.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for usage of `_.map_or(None, Some)`.
-
-### Why is this bad?
-Readability, this can be written more concisely as
-`_.ok()`.
-
-### Example
-```
-assert_eq!(Some(1), r.map_or(None, Some));
-```
-
-Use instead:
-```
-assert_eq!(Some(1), r.ok());
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/result_map_unit_fn.txt b/src/tools/clippy/src/docs/result_map_unit_fn.txt
deleted file mode 100644
index 3455c5c1f9b..00000000000
--- a/src/tools/clippy/src/docs/result_map_unit_fn.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for usage of `result.map(f)` where f is a function
-or closure that returns the unit type `()`.
-
-### Why is this bad?
-Readability, this can be written more clearly with
-an if let statement
-
-### Example
-```
-let x: Result<String, String> = do_stuff();
-x.map(log_err_msg);
-x.map(|msg| log_err_msg(format_msg(msg)));
-```
-
-The correct use would be:
-
-```
-let x: Result<String, String> = do_stuff();
-if let Ok(msg) = x {
-    log_err_msg(msg);
-};
-if let Ok(msg) = x {
-    log_err_msg(format_msg(msg));
-};
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/result_unit_err.txt b/src/tools/clippy/src/docs/result_unit_err.txt
deleted file mode 100644
index 7c8ec2ffcf9..00000000000
--- a/src/tools/clippy/src/docs/result_unit_err.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-### What it does
-Checks for public functions that return a `Result`
-with an `Err` type of `()`. It suggests using a custom type that
-implements `std::error::Error`.
-
-### Why is this bad?
-Unit does not implement `Error` and carries no
-further information about what went wrong.
-
-### Known problems
-Of course, this lint assumes that `Result` is used
-for a fallible operation (which is after all the intended use). However
-code may opt to (mis)use it as a basic two-variant-enum. In that case,
-the suggestion is misguided, and the code should use a custom enum
-instead.
-
-### Examples
-```
-pub fn read_u8() -> Result<u8, ()> { Err(()) }
-```
-should become
-```
-use std::fmt;
-
-#[derive(Debug)]
-pub struct EndOfStream;
-
-impl fmt::Display for EndOfStream {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "End of Stream")
-    }
-}
-
-impl std::error::Error for EndOfStream { }
-
-pub fn read_u8() -> Result<u8, EndOfStream> { Err(EndOfStream) }
-```
-
-Note that there are crates that simplify creating the error type, e.g.
-[`thiserror`](https://docs.rs/thiserror).
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/return_self_not_must_use.txt b/src/tools/clippy/src/docs/return_self_not_must_use.txt
deleted file mode 100644
index 4a4fd2c6e51..00000000000
--- a/src/tools/clippy/src/docs/return_self_not_must_use.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-### What it does
-This lint warns when a method returning `Self` doesn't have the `#[must_use]` attribute.
-
-### Why is this bad?
-Methods returning `Self` often create new values, having the `#[must_use]` attribute
-prevents users from "forgetting" to use the newly created value.
-
-The `#[must_use]` attribute can be added to the type itself to ensure that instances
-are never forgotten. Functions returning a type marked with `#[must_use]` will not be
-linted, as the usage is already enforced by the type attribute.
-
-### Limitations
-This lint is only applied on methods taking a `self` argument. It would be mostly noise
-if it was added on constructors for example.
-
-### Example
-```
-pub struct Bar;
-impl Bar {
-    // Missing attribute
-    pub fn bar(&self) -> Self {
-        Self
-    }
-}
-```
-
-Use instead:
-```
-// It's better to have the `#[must_use]` attribute on the method like this:
-pub struct Bar;
-impl Bar {
-    #[must_use]
-    pub fn bar(&self) -> Self {
-        Self
-    }
-}
-
-// Or on the type definition like this:
-#[must_use]
-pub struct Bar;
-impl Bar {
-    pub fn bar(&self) -> Self {
-        Self
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/reversed_empty_ranges.txt b/src/tools/clippy/src/docs/reversed_empty_ranges.txt
deleted file mode 100644
index 39f48119386..00000000000
--- a/src/tools/clippy/src/docs/reversed_empty_ranges.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for range expressions `x..y` where both `x` and `y`
-are constant and `x` is greater or equal to `y`.
-
-### Why is this bad?
-Empty ranges yield no values so iterating them is a no-op.
-Moreover, trying to use a reversed range to index a slice will panic at run-time.
-
-### Example
-```
-fn main() {
-    (10..=0).for_each(|x| println!("{}", x));
-
-    let arr = [1, 2, 3, 4, 5];
-    let sub = &arr[3..1];
-}
-```
-Use instead:
-```
-fn main() {
-    (0..=10).rev().for_each(|x| println!("{}", x));
-
-    let arr = [1, 2, 3, 4, 5];
-    let sub = &arr[1..3];
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/same_functions_in_if_condition.txt b/src/tools/clippy/src/docs/same_functions_in_if_condition.txt
deleted file mode 100644
index a0a90eec681..00000000000
--- a/src/tools/clippy/src/docs/same_functions_in_if_condition.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-### What it does
-Checks for consecutive `if`s with the same function call.
-
-### Why is this bad?
-This is probably a copy & paste error.
-Despite the fact that function can have side effects and `if` works as
-intended, such an approach is implicit and can be considered a "code smell".
-
-### Example
-```
-if foo() == bar {
-    …
-} else if foo() == bar {
-    …
-}
-```
-
-This probably should be:
-```
-if foo() == bar {
-    …
-} else if foo() == baz {
-    …
-}
-```
-
-or if the original code was not a typo and called function mutates a state,
-consider move the mutation out of the `if` condition to avoid similarity to
-a copy & paste error:
-
-```
-let first = foo();
-if first == bar {
-    …
-} else {
-    let second = foo();
-    if second == bar {
-    …
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/same_item_push.txt b/src/tools/clippy/src/docs/same_item_push.txt
deleted file mode 100644
index 7e724073f8a..00000000000
--- a/src/tools/clippy/src/docs/same_item_push.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Checks whether a for loop is being used to push a constant
-value into a Vec.
-
-### Why is this bad?
-This kind of operation can be expressed more succinctly with
-`vec![item; SIZE]` or `vec.resize(NEW_SIZE, item)` and using these alternatives may also
-have better performance.
-
-### Example
-```
-let item1 = 2;
-let item2 = 3;
-let mut vec: Vec<u8> = Vec::new();
-for _ in 0..20 {
-   vec.push(item1);
-}
-for _ in 0..30 {
-    vec.push(item2);
-}
-```
-
-Use instead:
-```
-let item1 = 2;
-let item2 = 3;
-let mut vec: Vec<u8> = vec![item1; 20];
-vec.resize(20 + 30, item2);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/same_name_method.txt b/src/tools/clippy/src/docs/same_name_method.txt
deleted file mode 100644
index 792dd717fc6..00000000000
--- a/src/tools/clippy/src/docs/same_name_method.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-It lints if a struct has two methods with the same name:
-one from a trait, another not from trait.
-
-### Why is this bad?
-Confusing.
-
-### Example
-```
-trait T {
-    fn foo(&self) {}
-}
-
-struct S;
-
-impl T for S {
-    fn foo(&self) {}
-}
-
-impl S {
-    fn foo(&self) {}
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/search_is_some.txt b/src/tools/clippy/src/docs/search_is_some.txt
deleted file mode 100644
index 67292d54585..00000000000
--- a/src/tools/clippy/src/docs/search_is_some.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for an iterator or string search (such as `find()`,
-`position()`, or `rposition()`) followed by a call to `is_some()` or `is_none()`.
-
-### Why is this bad?
-Readability, this can be written more concisely as:
-* `_.any(_)`, or `_.contains(_)` for `is_some()`,
-* `!_.any(_)`, or `!_.contains(_)` for `is_none()`.
-
-### Example
-```
-let vec = vec![1];
-vec.iter().find(|x| **x == 0).is_some();
-
-"hello world".find("world").is_none();
-```
-
-Use instead:
-```
-let vec = vec![1];
-vec.iter().any(|x| *x == 0);
-
-!"hello world".contains("world");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/self_assignment.txt b/src/tools/clippy/src/docs/self_assignment.txt
deleted file mode 100644
index ea60ea077ab..00000000000
--- a/src/tools/clippy/src/docs/self_assignment.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-### What it does
-Checks for explicit self-assignments.
-
-### Why is this bad?
-Self-assignments are redundant and unlikely to be
-intentional.
-
-### Known problems
-If expression contains any deref coercions or
-indexing operations they are assumed not to have any side effects.
-
-### Example
-```
-struct Event {
-    x: i32,
-}
-
-fn copy_position(a: &mut Event, b: &Event) {
-    a.x = a.x;
-}
-```
-
-Should be:
-```
-struct Event {
-    x: i32,
-}
-
-fn copy_position(a: &mut Event, b: &Event) {
-    a.x = b.x;
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/self_named_constructors.txt b/src/tools/clippy/src/docs/self_named_constructors.txt
deleted file mode 100644
index a01669a8454..00000000000
--- a/src/tools/clippy/src/docs/self_named_constructors.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Warns when constructors have the same name as their types.
-
-### Why is this bad?
-Repeating the name of the type is redundant.
-
-### Example
-```
-struct Foo {}
-
-impl Foo {
-    pub fn foo() -> Foo {
-        Foo {}
-    }
-}
-```
-Use instead:
-```
-struct Foo {}
-
-impl Foo {
-    pub fn new() -> Foo {
-        Foo {}
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/self_named_module_files.txt b/src/tools/clippy/src/docs/self_named_module_files.txt
deleted file mode 100644
index 73e80513628..00000000000
--- a/src/tools/clippy/src/docs/self_named_module_files.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks that module layout uses only `mod.rs` files.
-
-### Why is this bad?
-Having multiple module layout styles in a project can be confusing.
-
-### Example
-```
-src/
-  stuff/
-    stuff_files.rs
-  stuff.rs
-  lib.rs
-```
-Use instead:
-```
-src/
-  stuff/
-    stuff_files.rs
-    mod.rs
-  lib.rs
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/semicolon_if_nothing_returned.txt b/src/tools/clippy/src/docs/semicolon_if_nothing_returned.txt
deleted file mode 100644
index 30c963ca211..00000000000
--- a/src/tools/clippy/src/docs/semicolon_if_nothing_returned.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Looks for blocks of expressions and fires if the last expression returns
-`()` but is not followed by a semicolon.
-
-### Why is this bad?
-The semicolon might be optional but when extending the block with new
-code, it doesn't require a change in previous last line.
-
-### Example
-```
-fn main() {
-    println!("Hello world")
-}
-```
-Use instead:
-```
-fn main() {
-    println!("Hello world");
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/separated_literal_suffix.txt b/src/tools/clippy/src/docs/separated_literal_suffix.txt
deleted file mode 100644
index 226a6b8a987..00000000000
--- a/src/tools/clippy/src/docs/separated_literal_suffix.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Warns if literal suffixes are separated by an underscore.
-To enforce separated literal suffix style,
-see the `unseparated_literal_suffix` lint.
-
-### Why is this bad?
-Suffix style should be consistent.
-
-### Example
-```
-123832_i32
-```
-
-Use instead:
-```
-123832i32
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/serde_api_misuse.txt b/src/tools/clippy/src/docs/serde_api_misuse.txt
deleted file mode 100644
index 8a3c89ac11a..00000000000
--- a/src/tools/clippy/src/docs/serde_api_misuse.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-### What it does
-Checks for mis-uses of the serde API.
-
-### Why is this bad?
-Serde is very finnicky about how its API should be
-used, but the type system can't be used to enforce it (yet?).
-
-### Example
-Implementing `Visitor::visit_string` but not
-`Visitor::visit_str`.
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/shadow_reuse.txt b/src/tools/clippy/src/docs/shadow_reuse.txt
deleted file mode 100644
index 9eb8e7ad164..00000000000
--- a/src/tools/clippy/src/docs/shadow_reuse.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for bindings that shadow other bindings already in
-scope, while reusing the original value.
-
-### Why is this bad?
-Not too much, in fact it's a common pattern in Rust
-code. Still, some argue that name shadowing like this hurts readability,
-because a value may be bound to different things depending on position in
-the code.
-
-### Example
-```
-let x = 2;
-let x = x + 1;
-```
-use different variable name:
-```
-let x = 2;
-let y = x + 1;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/shadow_same.txt b/src/tools/clippy/src/docs/shadow_same.txt
deleted file mode 100644
index 3cd96f560a5..00000000000
--- a/src/tools/clippy/src/docs/shadow_same.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for bindings that shadow other bindings already in
-scope, while just changing reference level or mutability.
-
-### Why is this bad?
-Not much, in fact it's a very common pattern in Rust
-code. Still, some may opt to avoid it in their code base, they can set this
-lint to `Warn`.
-
-### Example
-```
-let x = &x;
-```
-
-Use instead:
-```
-let y = &x; // use different variable name
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/shadow_unrelated.txt b/src/tools/clippy/src/docs/shadow_unrelated.txt
deleted file mode 100644
index 436251c520a..00000000000
--- a/src/tools/clippy/src/docs/shadow_unrelated.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for bindings that shadow other bindings already in
-scope, either without an initialization or with one that does not even use
-the original value.
-
-### Why is this bad?
-Name shadowing can hurt readability, especially in
-large code bases, because it is easy to lose track of the active binding at
-any place in the code. This can be alleviated by either giving more specific
-names to bindings or introducing more scopes to contain the bindings.
-
-### Example
-```
-let x = y;
-let x = z; // shadows the earlier binding
-```
-
-Use instead:
-```
-let x = y;
-let w = z; // use different variable name
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/short_circuit_statement.txt b/src/tools/clippy/src/docs/short_circuit_statement.txt
deleted file mode 100644
index 31492bed03d..00000000000
--- a/src/tools/clippy/src/docs/short_circuit_statement.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Checks for the use of short circuit boolean conditions as
-a
-statement.
-
-### Why is this bad?
-Using a short circuit boolean condition as a statement
-may hide the fact that the second part is executed or not depending on the
-outcome of the first part.
-
-### Example
-```
-f() && g(); // We should write `if f() { g(); }`.
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/should_implement_trait.txt b/src/tools/clippy/src/docs/should_implement_trait.txt
deleted file mode 100644
index 02e74751ae0..00000000000
--- a/src/tools/clippy/src/docs/should_implement_trait.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for methods that should live in a trait
-implementation of a `std` trait (see [llogiq's blog
-post](http://llogiq.github.io/2015/07/30/traits.html) for further
-information) instead of an inherent implementation.
-
-### Why is this bad?
-Implementing the traits improve ergonomics for users of
-the code, often with very little cost. Also people seeing a `mul(...)`
-method
-may expect `*` to work equally, so you should have good reason to disappoint
-them.
-
-### Example
-```
-struct X;
-impl X {
-    fn add(&self, other: &X) -> X {
-        // ..
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/significant_drop_in_scrutinee.txt b/src/tools/clippy/src/docs/significant_drop_in_scrutinee.txt
deleted file mode 100644
index f869def0ddb..00000000000
--- a/src/tools/clippy/src/docs/significant_drop_in_scrutinee.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-### What it does
-Check for temporaries returned from function calls in a match scrutinee that have the
-`clippy::has_significant_drop` attribute.
-
-### Why is this bad?
-The `clippy::has_significant_drop` attribute can be added to types whose Drop impls have
-an important side-effect, such as unlocking a mutex, making it important for users to be
-able to accurately understand their lifetimes. When a temporary is returned in a function
-call in a match scrutinee, its lifetime lasts until the end of the match block, which may
-be surprising.
-
-For `Mutex`es this can lead to a deadlock. This happens when the match scrutinee uses a
-function call that returns a `MutexGuard` and then tries to lock again in one of the match
-arms. In that case the `MutexGuard` in the scrutinee will not be dropped until the end of
-the match block and thus will not unlock.
-
-### Example
-```
-let mutex = Mutex::new(State {});
-
-match mutex.lock().unwrap().foo() {
-    true => {
-        mutex.lock().unwrap().bar(); // Deadlock!
-    }
-    false => {}
-};
-
-println!("All done!");
-```
-Use instead:
-```
-let mutex = Mutex::new(State {});
-
-let is_foo = mutex.lock().unwrap().foo();
-match is_foo {
-    true => {
-        mutex.lock().unwrap().bar();
-    }
-    false => {}
-};
-
-println!("All done!");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/similar_names.txt b/src/tools/clippy/src/docs/similar_names.txt
deleted file mode 100644
index f9eff21b679..00000000000
--- a/src/tools/clippy/src/docs/similar_names.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for names that are very similar and thus confusing.
-
-Note: this lint looks for similar names throughout each
-scope. To allow it, you need to allow it on the scope
-level, not on the name that is reported.
-
-### Why is this bad?
-It's hard to distinguish between names that differ only
-by a single character.
-
-### Example
-```
-let checked_exp = something;
-let checked_expr = something_else;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/single_char_add_str.txt b/src/tools/clippy/src/docs/single_char_add_str.txt
deleted file mode 100644
index cf23dc0c89b..00000000000
--- a/src/tools/clippy/src/docs/single_char_add_str.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Warns when using `push_str`/`insert_str` with a single-character string literal
-where `push`/`insert` with a `char` would work fine.
-
-### Why is this bad?
-It's less clear that we are pushing a single character.
-
-### Example
-```
-string.insert_str(0, "R");
-string.push_str("R");
-```
-
-Use instead:
-```
-string.insert(0, 'R');
-string.push('R');
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/single_char_lifetime_names.txt b/src/tools/clippy/src/docs/single_char_lifetime_names.txt
deleted file mode 100644
index 92dd24bf247..00000000000
--- a/src/tools/clippy/src/docs/single_char_lifetime_names.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-### What it does
-Checks for lifetimes with names which are one character
-long.
-
-### Why is this bad?
-A single character is likely not enough to express the
-purpose of a lifetime. Using a longer name can make code
-easier to understand, especially for those who are new to
-Rust.
-
-### Known problems
-Rust programmers and learning resources tend to use single
-character lifetimes, so this lint is at odds with the
-ecosystem at large. In addition, the lifetime's purpose may
-be obvious or, rarely, expressible in one character.
-
-### Example
-```
-struct DiagnosticCtx<'a> {
-    source: &'a str,
-}
-```
-Use instead:
-```
-struct DiagnosticCtx<'src> {
-    source: &'src str,
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/single_char_pattern.txt b/src/tools/clippy/src/docs/single_char_pattern.txt
deleted file mode 100644
index 9e5ad1e7d63..00000000000
--- a/src/tools/clippy/src/docs/single_char_pattern.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for string methods that receive a single-character
-`str` as an argument, e.g., `_.split("x")`.
-
-### Why is this bad?
-Performing these methods using a `char` is faster than
-using a `str`.
-
-### Known problems
-Does not catch multi-byte unicode characters.
-
-### Example
-```
-_.split("x");
-```
-
-Use instead:
-```
-_.split('x');
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/single_component_path_imports.txt b/src/tools/clippy/src/docs/single_component_path_imports.txt
deleted file mode 100644
index 3a026388183..00000000000
--- a/src/tools/clippy/src/docs/single_component_path_imports.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checking for imports with single component use path.
-
-### Why is this bad?
-Import with single component use path such as `use cratename;`
-is not necessary, and thus should be removed.
-
-### Example
-```
-use regex;
-
-fn main() {
-    regex::Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
-}
-```
-Better as
-```
-fn main() {
-    regex::Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/single_element_loop.txt b/src/tools/clippy/src/docs/single_element_loop.txt
deleted file mode 100644
index 6f0c15a85f7..00000000000
--- a/src/tools/clippy/src/docs/single_element_loop.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks whether a for loop has a single element.
-
-### Why is this bad?
-There is no reason to have a loop of a
-single element.
-
-### Example
-```
-let item1 = 2;
-for item in &[item1] {
-    println!("{}", item);
-}
-```
-
-Use instead:
-```
-let item1 = 2;
-let item = &item1;
-println!("{}", item);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/single_match.txt b/src/tools/clippy/src/docs/single_match.txt
deleted file mode 100644
index 31dde4da848..00000000000
--- a/src/tools/clippy/src/docs/single_match.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for matches with a single arm where an `if let`
-will usually suffice.
-
-### Why is this bad?
-Just readability – `if let` nests less than a `match`.
-
-### Example
-```
-match x {
-    Some(ref foo) => bar(foo),
-    _ => (),
-}
-```
-
-Use instead:
-```
-if let Some(ref foo) = x {
-    bar(foo);
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/single_match_else.txt b/src/tools/clippy/src/docs/single_match_else.txt
deleted file mode 100644
index 29a447af09b..00000000000
--- a/src/tools/clippy/src/docs/single_match_else.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Checks for matches with two arms where an `if let else` will
-usually suffice.
-
-### Why is this bad?
-Just readability – `if let` nests less than a `match`.
-
-### Known problems
-Personal style preferences may differ.
-
-### Example
-Using `match`:
-
-```
-match x {
-    Some(ref foo) => bar(foo),
-    _ => bar(&other_ref),
-}
-```
-
-Using `if let` with `else`:
-
-```
-if let Some(ref foo) = x {
-    bar(foo);
-} else {
-    bar(&other_ref);
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/size_of_in_element_count.txt b/src/tools/clippy/src/docs/size_of_in_element_count.txt
deleted file mode 100644
index d893ec6a2a0..00000000000
--- a/src/tools/clippy/src/docs/size_of_in_element_count.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Detects expressions where
-`size_of::<T>` or `size_of_val::<T>` is used as a
-count of elements of type `T`
-
-### Why is this bad?
-These functions expect a count
-of `T` and not a number of bytes
-
-### Example
-```
-const SIZE: usize = 128;
-let x = [2u8; SIZE];
-let mut y = [2u8; SIZE];
-unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/skip_while_next.txt b/src/tools/clippy/src/docs/skip_while_next.txt
deleted file mode 100644
index 1ec8a3a28d5..00000000000
--- a/src/tools/clippy/src/docs/skip_while_next.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for usage of `_.skip_while(condition).next()`.
-
-### Why is this bad?
-Readability, this can be written more concisely as
-`_.find(!condition)`.
-
-### Example
-```
-vec.iter().skip_while(|x| **x == 0).next();
-```
-
-Use instead:
-```
-vec.iter().find(|x| **x != 0);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/slow_vector_initialization.txt b/src/tools/clippy/src/docs/slow_vector_initialization.txt
deleted file mode 100644
index 53442e17965..00000000000
--- a/src/tools/clippy/src/docs/slow_vector_initialization.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks slow zero-filled vector initialization
-
-### Why is this bad?
-These structures are non-idiomatic and less efficient than simply using
-`vec![0; len]`.
-
-### Example
-```
-let mut vec1 = Vec::with_capacity(len);
-vec1.resize(len, 0);
-
-let mut vec1 = Vec::with_capacity(len);
-vec1.resize(vec1.capacity(), 0);
-
-let mut vec2 = Vec::with_capacity(len);
-vec2.extend(repeat(0).take(len));
-```
-
-Use instead:
-```
-let mut vec1 = vec![0; len];
-let mut vec2 = vec![0; len];
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/stable_sort_primitive.txt b/src/tools/clippy/src/docs/stable_sort_primitive.txt
deleted file mode 100644
index 6465dbee46b..00000000000
--- a/src/tools/clippy/src/docs/stable_sort_primitive.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-### What it does
-When sorting primitive values (integers, bools, chars, as well
-as arrays, slices, and tuples of such items), it is typically better to
-use an unstable sort than a stable sort.
-
-### Why is this bad?
-Typically, using a stable sort consumes more memory and cpu cycles.
-Because values which compare equal are identical, preserving their
-relative order (the guarantee that a stable sort provides) means
-nothing, while the extra costs still apply.
-
-### Known problems
-
-As pointed out in
-[issue #8241](https://github.com/rust-lang/rust-clippy/issues/8241),
-a stable sort can instead be significantly faster for certain scenarios
-(eg. when a sorted vector is extended with new data and resorted).
-
-For more information and benchmarking results, please refer to the
-issue linked above.
-
-### Example
-```
-let mut vec = vec![2, 1, 3];
-vec.sort();
-```
-Use instead:
-```
-let mut vec = vec![2, 1, 3];
-vec.sort_unstable();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/std_instead_of_alloc.txt b/src/tools/clippy/src/docs/std_instead_of_alloc.txt
deleted file mode 100644
index c2d32704e50..00000000000
--- a/src/tools/clippy/src/docs/std_instead_of_alloc.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-
-Finds items imported through `std` when available through `alloc`.
-
-### Why is this bad?
-
-Crates which have `no_std` compatibility and require alloc may wish to ensure types are imported from
-alloc to ensure disabling `std` does not cause the crate to fail to compile. This lint is also useful
-for crates migrating to become `no_std` compatible.
-
-### Example
-```
-use std::vec::Vec;
-```
-Use instead:
-```
-use alloc::vec::Vec;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/std_instead_of_core.txt b/src/tools/clippy/src/docs/std_instead_of_core.txt
deleted file mode 100644
index f1e1518c6a6..00000000000
--- a/src/tools/clippy/src/docs/std_instead_of_core.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-
-Finds items imported through `std` when available through `core`.
-
-### Why is this bad?
-
-Crates which have `no_std` compatibility may wish to ensure types are imported from core to ensure
-disabling `std` does not cause the crate to fail to compile. This lint is also useful for crates
-migrating to become `no_std` compatible.
-
-### Example
-```
-use std::hash::Hasher;
-```
-Use instead:
-```
-use core::hash::Hasher;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/str_to_string.txt b/src/tools/clippy/src/docs/str_to_string.txt
deleted file mode 100644
index a2475522374..00000000000
--- a/src/tools/clippy/src/docs/str_to_string.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-This lint checks for `.to_string()` method calls on values of type `&str`.
-
-### Why is this bad?
-The `to_string` method is also used on other types to convert them to a string.
-When called on a `&str` it turns the `&str` into the owned variant `String`, which can be better
-expressed with `.to_owned()`.
-
-### Example
-```
-// example code where clippy issues a warning
-let _ = "str".to_string();
-```
-Use instead:
-```
-// example code which does not raise clippy warning
-let _ = "str".to_owned();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/string_add.txt b/src/tools/clippy/src/docs/string_add.txt
deleted file mode 100644
index 23dafd0d033..00000000000
--- a/src/tools/clippy/src/docs/string_add.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for all instances of `x + _` where `x` is of type
-`String`, but only if [`string_add_assign`](#string_add_assign) does *not*
-match.
-
-### Why is this bad?
-It's not bad in and of itself. However, this particular
-`Add` implementation is asymmetric (the other operand need not be `String`,
-but `x` does), while addition as mathematically defined is symmetric, also
-the `String::push_str(_)` function is a perfectly good replacement.
-Therefore, some dislike it and wish not to have it in their code.
-
-That said, other people think that string addition, having a long tradition
-in other languages is actually fine, which is why we decided to make this
-particular lint `allow` by default.
-
-### Example
-```
-let x = "Hello".to_owned();
-x + ", World";
-```
-
-Use instead:
-```
-let mut x = "Hello".to_owned();
-x.push_str(", World");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/string_add_assign.txt b/src/tools/clippy/src/docs/string_add_assign.txt
deleted file mode 100644
index 7438be855db..00000000000
--- a/src/tools/clippy/src/docs/string_add_assign.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for string appends of the form `x = x + y` (without
-`let`!).
-
-### Why is this bad?
-It's not really bad, but some people think that the
-`.push_str(_)` method is more readable.
-
-### Example
-```
-let mut x = "Hello".to_owned();
-x = x + ", World";
-
-// More readable
-x += ", World";
-x.push_str(", World");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/string_extend_chars.txt b/src/tools/clippy/src/docs/string_extend_chars.txt
deleted file mode 100644
index 619ea3e1186..00000000000
--- a/src/tools/clippy/src/docs/string_extend_chars.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for the use of `.extend(s.chars())` where s is a
-`&str` or `String`.
-
-### Why is this bad?
-`.push_str(s)` is clearer
-
-### Example
-```
-let abc = "abc";
-let def = String::from("def");
-let mut s = String::new();
-s.extend(abc.chars());
-s.extend(def.chars());
-```
-The correct use would be:
-```
-let abc = "abc";
-let def = String::from("def");
-let mut s = String::new();
-s.push_str(abc);
-s.push_str(&def);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/string_from_utf8_as_bytes.txt b/src/tools/clippy/src/docs/string_from_utf8_as_bytes.txt
deleted file mode 100644
index 9102d73471c..00000000000
--- a/src/tools/clippy/src/docs/string_from_utf8_as_bytes.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Check if the string is transformed to byte array and casted back to string.
-
-### Why is this bad?
-It's unnecessary, the string can be used directly.
-
-### Example
-```
-std::str::from_utf8(&"Hello World!".as_bytes()[6..11]).unwrap();
-```
-
-Use instead:
-```
-&"Hello World!"[6..11];
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/string_lit_as_bytes.txt b/src/tools/clippy/src/docs/string_lit_as_bytes.txt
deleted file mode 100644
index a125b97ed65..00000000000
--- a/src/tools/clippy/src/docs/string_lit_as_bytes.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-### What it does
-Checks for the `as_bytes` method called on string literals
-that contain only ASCII characters.
-
-### Why is this bad?
-Byte string literals (e.g., `b"foo"`) can be used
-instead. They are shorter but less discoverable than `as_bytes()`.
-
-### Known problems
-`"str".as_bytes()` and the suggested replacement of `b"str"` are not
-equivalent because they have different types. The former is `&[u8]`
-while the latter is `&[u8; 3]`. That means in general they will have a
-different set of methods and different trait implementations.
-
-```
-fn f(v: Vec<u8>) {}
-
-f("...".as_bytes().to_owned()); // works
-f(b"...".to_owned()); // does not work, because arg is [u8; 3] not Vec<u8>
-
-fn g(r: impl std::io::Read) {}
-
-g("...".as_bytes()); // works
-g(b"..."); // does not work
-```
-
-The actual equivalent of `"str".as_bytes()` with the same type is not
-`b"str"` but `&b"str"[..]`, which is a great deal of punctuation and not
-more readable than a function call.
-
-### Example
-```
-let bstr = "a byte string".as_bytes();
-```
-
-Use instead:
-```
-let bstr = b"a byte string";
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/string_slice.txt b/src/tools/clippy/src/docs/string_slice.txt
deleted file mode 100644
index 3d9e49dd39e..00000000000
--- a/src/tools/clippy/src/docs/string_slice.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for slice operations on strings
-
-### Why is this bad?
-UTF-8 characters span multiple bytes, and it is easy to inadvertently confuse character
-counts and string indices. This may lead to panics, and should warrant some test cases
-containing wide UTF-8 characters. This lint is most useful in code that should avoid
-panics at all costs.
-
-### Known problems
-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
-```
-&"Ölkanne"[1..];
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/string_to_string.txt b/src/tools/clippy/src/docs/string_to_string.txt
deleted file mode 100644
index deb7eebe784..00000000000
--- a/src/tools/clippy/src/docs/string_to_string.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-This lint checks for `.to_string()` method calls on values of type `String`.
-
-### Why is this bad?
-The `to_string` method is also used on other types to convert them to a string.
-When called on a `String` it only clones the `String`, which can be better expressed with `.clone()`.
-
-### Example
-```
-// example code where clippy issues a warning
-let msg = String::from("Hello World");
-let _ = msg.to_string();
-```
-Use instead:
-```
-// example code which does not raise clippy warning
-let msg = String::from("Hello World");
-let _ = msg.clone();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/strlen_on_c_strings.txt b/src/tools/clippy/src/docs/strlen_on_c_strings.txt
deleted file mode 100644
index 0454abf55a2..00000000000
--- a/src/tools/clippy/src/docs/strlen_on_c_strings.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for usage of `libc::strlen` on a `CString` or `CStr` value,
-and suggest calling `as_bytes().len()` or `to_bytes().len()` respectively instead.
-
-### Why is this bad?
-This avoids calling an unsafe `libc` function.
-Currently, it also avoids calculating the length.
-
-### Example
-```
-use std::ffi::CString;
-let cstring = CString::new("foo").expect("CString::new failed");
-let len = unsafe { libc::strlen(cstring.as_ptr()) };
-```
-Use instead:
-```
-use std::ffi::CString;
-let cstring = CString::new("foo").expect("CString::new failed");
-let len = cstring.as_bytes().len();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/struct_excessive_bools.txt b/src/tools/clippy/src/docs/struct_excessive_bools.txt
deleted file mode 100644
index 9e197c78620..00000000000
--- a/src/tools/clippy/src/docs/struct_excessive_bools.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-### What it does
-Checks for excessive
-use of bools in structs.
-
-### Why is this bad?
-Excessive bools in a struct
-is often a sign that it's used as a state machine,
-which is much better implemented as an enum.
-If it's not the case, excessive bools usually benefit
-from refactoring into two-variant enums for better
-readability and API.
-
-### Example
-```
-struct S {
-    is_pending: bool,
-    is_processing: bool,
-    is_finished: bool,
-}
-```
-
-Use instead:
-```
-enum S {
-    Pending,
-    Processing,
-    Finished,
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/suboptimal_flops.txt b/src/tools/clippy/src/docs/suboptimal_flops.txt
deleted file mode 100644
index f1c9c665b08..00000000000
--- a/src/tools/clippy/src/docs/suboptimal_flops.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-### What it does
-Looks for floating-point expressions that
-can be expressed using built-in methods to improve both
-accuracy and performance.
-
-### Why is this bad?
-Negatively impacts accuracy and performance.
-
-### Example
-```
-use std::f32::consts::E;
-
-let a = 3f32;
-let _ = (2f32).powf(a);
-let _ = E.powf(a);
-let _ = a.powf(1.0 / 2.0);
-let _ = a.log(2.0);
-let _ = a.log(10.0);
-let _ = a.log(E);
-let _ = a.powf(2.0);
-let _ = a * 2.0 + 4.0;
-let _ = if a < 0.0 {
-    -a
-} else {
-    a
-};
-let _ = if a < 0.0 {
-    a
-} else {
-    -a
-};
-```
-
-is better expressed as
-
-```
-use std::f32::consts::E;
-
-let a = 3f32;
-let _ = a.exp2();
-let _ = a.exp();
-let _ = a.sqrt();
-let _ = a.log2();
-let _ = a.log10();
-let _ = a.ln();
-let _ = a.powi(2);
-let _ = a.mul_add(2.0, 4.0);
-let _ = a.abs();
-let _ = -a.abs();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/suspicious_arithmetic_impl.txt b/src/tools/clippy/src/docs/suspicious_arithmetic_impl.txt
deleted file mode 100644
index d67ff279346..00000000000
--- a/src/tools/clippy/src/docs/suspicious_arithmetic_impl.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Lints for suspicious operations in impls of arithmetic operators, e.g.
-subtracting elements in an Add impl.
-
-### Why is this bad?
-This is probably a typo or copy-and-paste error and not intended.
-
-### Example
-```
-impl Add for Foo {
-    type Output = Foo;
-
-    fn add(self, other: Foo) -> Foo {
-        Foo(self.0 - other.0)
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/suspicious_assignment_formatting.txt b/src/tools/clippy/src/docs/suspicious_assignment_formatting.txt
deleted file mode 100644
index b889827cdf2..00000000000
--- a/src/tools/clippy/src/docs/suspicious_assignment_formatting.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for use of the non-existent `=*`, `=!` and `=-`
-operators.
-
-### Why is this bad?
-This is either a typo of `*=`, `!=` or `-=` or
-confusing.
-
-### Example
-```
-a =- 42; // confusing, should it be `a -= 42` or `a = -42`?
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/suspicious_else_formatting.txt b/src/tools/clippy/src/docs/suspicious_else_formatting.txt
deleted file mode 100644
index 3cf2f74868e..00000000000
--- a/src/tools/clippy/src/docs/suspicious_else_formatting.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-### What it does
-Checks for formatting of `else`. It lints if the `else`
-is followed immediately by a newline or the `else` seems to be missing.
-
-### Why is this bad?
-This is probably some refactoring remnant, even if the
-code is correct, it might look confusing.
-
-### Example
-```
-if foo {
-} { // looks like an `else` is missing here
-}
-
-if foo {
-} if bar { // looks like an `else` is missing here
-}
-
-if foo {
-} else
-
-{ // this is the `else` block of the previous `if`, but should it be?
-}
-
-if foo {
-} else
-
-if bar { // this is the `else` block of the previous `if`, but should it be?
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/suspicious_map.txt b/src/tools/clippy/src/docs/suspicious_map.txt
deleted file mode 100644
index d8fa52c43fb..00000000000
--- a/src/tools/clippy/src/docs/suspicious_map.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-### What it does
-Checks for calls to `map` followed by a `count`.
-
-### Why is this bad?
-It looks suspicious. Maybe `map` was confused with `filter`.
-If the `map` call is intentional, this should be rewritten
-using `inspect`. Or, if you intend to drive the iterator to
-completion, you can just use `for_each` instead.
-
-### Example
-```
-let _ = (0..3).map(|x| x + 2).count();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/suspicious_op_assign_impl.txt b/src/tools/clippy/src/docs/suspicious_op_assign_impl.txt
deleted file mode 100644
index 81abfbecae0..00000000000
--- a/src/tools/clippy/src/docs/suspicious_op_assign_impl.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Lints for suspicious operations in impls of OpAssign, e.g.
-subtracting elements in an AddAssign impl.
-
-### Why is this bad?
-This is probably a typo or copy-and-paste error and not intended.
-
-### Example
-```
-impl AddAssign for Foo {
-    fn add_assign(&mut self, other: Foo) {
-        *self = *self - other;
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/suspicious_operation_groupings.txt b/src/tools/clippy/src/docs/suspicious_operation_groupings.txt
deleted file mode 100644
index 81ede5d3da5..00000000000
--- a/src/tools/clippy/src/docs/suspicious_operation_groupings.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-### What it does
-Checks for unlikely usages of binary operators that are almost
-certainly typos and/or copy/paste errors, given the other usages
-of binary operators nearby.
-
-### Why is this bad?
-They are probably bugs and if they aren't then they look like bugs
-and you should add a comment explaining why you are doing such an
-odd set of operations.
-
-### Known problems
-There may be some false positives if you are trying to do something
-unusual that happens to look like a typo.
-
-### Example
-```
-struct Vec3 {
-    x: f64,
-    y: f64,
-    z: f64,
-}
-
-impl Eq for Vec3 {}
-
-impl PartialEq for Vec3 {
-    fn eq(&self, other: &Self) -> bool {
-        // This should trigger the lint because `self.x` is compared to `other.y`
-        self.x == other.y && self.y == other.y && self.z == other.z
-    }
-}
-```
-Use instead:
-```
-// same as above except:
-impl PartialEq for Vec3 {
-    fn eq(&self, other: &Self) -> bool {
-        // Note we now compare other.x to self.x
-        self.x == other.x && self.y == other.y && self.z == other.z
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/suspicious_splitn.txt b/src/tools/clippy/src/docs/suspicious_splitn.txt
deleted file mode 100644
index 79a3dbfa6f4..00000000000
--- a/src/tools/clippy/src/docs/suspicious_splitn.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for calls to [`splitn`]
-(https://doc.rust-lang.org/std/primitive.str.html#method.splitn) and
-related functions with either zero or one splits.
-
-### Why is this bad?
-These calls don't actually split the value and are
-likely to be intended as a different number.
-
-### Example
-```
-for x in s.splitn(1, ":") {
-    // ..
-}
-```
-
-Use instead:
-```
-for x in s.splitn(2, ":") {
-    // ..
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/suspicious_to_owned.txt b/src/tools/clippy/src/docs/suspicious_to_owned.txt
deleted file mode 100644
index 8cbf61dc717..00000000000
--- a/src/tools/clippy/src/docs/suspicious_to_owned.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-### What it does
-Checks for the usage of `_.to_owned()`, on a `Cow<'_, _>`.
-
-### Why is this bad?
-Calling `to_owned()` on a `Cow` creates a clone of the `Cow`
-itself, without taking ownership of the `Cow` contents (i.e.
-it's equivalent to calling `Cow::clone`).
-The similarly named `into_owned` method, on the other hand,
-clones the `Cow` contents, effectively turning any `Cow::Borrowed`
-into a `Cow::Owned`.
-
-Given the potential ambiguity, consider replacing `to_owned`
-with `clone` for better readability or, if getting a `Cow::Owned`
-was the original intent, using `into_owned` instead.
-
-### Example
-```
-let s = "Hello world!";
-let cow = Cow::Borrowed(s);
-
-let data = cow.to_owned();
-assert!(matches!(data, Cow::Borrowed(_)))
-```
-Use instead:
-```
-let s = "Hello world!";
-let cow = Cow::Borrowed(s);
-
-let data = cow.clone();
-assert!(matches!(data, Cow::Borrowed(_)))
-```
-or
-```
-let s = "Hello world!";
-let cow = Cow::Borrowed(s);
-
-let data = cow.into_owned();
-assert!(matches!(data, String))
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/suspicious_unary_op_formatting.txt b/src/tools/clippy/src/docs/suspicious_unary_op_formatting.txt
deleted file mode 100644
index 06fb09db76d..00000000000
--- a/src/tools/clippy/src/docs/suspicious_unary_op_formatting.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks the formatting of a unary operator on the right hand side
-of a binary operator. It lints if there is no space between the binary and unary operators,
-but there is a space between the unary and its operand.
-
-### Why is this bad?
-This is either a typo in the binary operator or confusing.
-
-### Example
-```
-// &&! looks like a different operator
-if foo &&! bar {}
-```
-
-Use instead:
-```
-if foo && !bar {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/swap_ptr_to_ref.txt b/src/tools/clippy/src/docs/swap_ptr_to_ref.txt
deleted file mode 100644
index 0215d1e8a42..00000000000
--- a/src/tools/clippy/src/docs/swap_ptr_to_ref.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for calls to `core::mem::swap` where either parameter is derived from a pointer
-
-### Why is this bad?
-When at least one parameter to `swap` is derived from a pointer it may overlap with the
-other. This would then lead to undefined behavior.
-
-### Example
-```
-unsafe fn swap(x: &[*mut u32], y: &[*mut u32]) {
-    for (&x, &y) in x.iter().zip(y) {
-        core::mem::swap(&mut *x, &mut *y);
-    }
-}
-```
-Use instead:
-```
-unsafe fn swap(x: &[*mut u32], y: &[*mut u32]) {
-    for (&x, &y) in x.iter().zip(y) {
-        core::ptr::swap(x, y);
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/tabs_in_doc_comments.txt b/src/tools/clippy/src/docs/tabs_in_doc_comments.txt
deleted file mode 100644
index f83dbe2b73c..00000000000
--- a/src/tools/clippy/src/docs/tabs_in_doc_comments.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-### What it does
-Checks doc comments for usage of tab characters.
-
-### Why is this bad?
-The rust style-guide promotes spaces instead of tabs for indentation.
-To keep a consistent view on the source, also doc comments should not have tabs.
-Also, explaining ascii-diagrams containing tabs can get displayed incorrectly when the
-display settings of the author and reader differ.
-
-### Example
-```
-///
-/// Struct to hold two strings:
-/// 	- first		one
-/// 	- second	one
-pub struct DoubleString {
-   ///
-   /// 	- First String:
-   /// 		- needs to be inside here
-   first_string: String,
-   ///
-   /// 	- Second String:
-   /// 		- needs to be inside here
-   second_string: String,
-}
-```
-
-Will be converted to:
-```
-///
-/// Struct to hold two strings:
-///     - first        one
-///     - second    one
-pub struct DoubleString {
-   ///
-   ///     - First String:
-   ///         - needs to be inside here
-   first_string: String,
-   ///
-   ///     - Second String:
-   ///         - needs to be inside here
-   second_string: String,
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/temporary_assignment.txt b/src/tools/clippy/src/docs/temporary_assignment.txt
deleted file mode 100644
index 195b42cf0d4..00000000000
--- a/src/tools/clippy/src/docs/temporary_assignment.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for construction of a structure or tuple just to
-assign a value in it.
-
-### Why is this bad?
-Readability. If the structure is only created to be
-updated, why not write the structure you want in the first place?
-
-### Example
-```
-(0, 0).0 = 1
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/to_digit_is_some.txt b/src/tools/clippy/src/docs/to_digit_is_some.txt
deleted file mode 100644
index eee8375adf7..00000000000
--- a/src/tools/clippy/src/docs/to_digit_is_some.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for `.to_digit(..).is_some()` on `char`s.
-
-### Why is this bad?
-This is a convoluted way of checking if a `char` is a digit. It's
-more straight forward to use the dedicated `is_digit` method.
-
-### Example
-```
-let is_digit = c.to_digit(radix).is_some();
-```
-can be written as:
-```
-let is_digit = c.is_digit(radix);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/to_string_in_format_args.txt b/src/tools/clippy/src/docs/to_string_in_format_args.txt
deleted file mode 100644
index 34b20583585..00000000000
--- a/src/tools/clippy/src/docs/to_string_in_format_args.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for [`ToString::to_string`](https://doc.rust-lang.org/std/string/trait.ToString.html#tymethod.to_string)
-applied to a type that implements [`Display`](https://doc.rust-lang.org/std/fmt/trait.Display.html)
-in a macro that does formatting.
-
-### Why is this bad?
-Since the type implements `Display`, the use of `to_string` is
-unnecessary.
-
-### Example
-```
-println!("error: something failed at {}", Location::caller().to_string());
-```
-Use instead:
-```
-println!("error: something failed at {}", Location::caller());
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/todo.txt b/src/tools/clippy/src/docs/todo.txt
deleted file mode 100644
index 661eb1ac5cf..00000000000
--- a/src/tools/clippy/src/docs/todo.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-### What it does
-Checks for usage of `todo!`.
-
-### Why is this bad?
-This macro should not be present in production code
-
-### Example
-```
-todo!();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/too_many_arguments.txt b/src/tools/clippy/src/docs/too_many_arguments.txt
deleted file mode 100644
index 4669f9f82e6..00000000000
--- a/src/tools/clippy/src/docs/too_many_arguments.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Checks for functions with too many parameters.
-
-### Why is this bad?
-Functions with lots of parameters are considered bad
-style and reduce readability (“what does the 5th parameter mean?”). Consider
-grouping some parameters into a new type.
-
-### Example
-```
-fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) {
-    // ..
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/too_many_lines.txt b/src/tools/clippy/src/docs/too_many_lines.txt
deleted file mode 100644
index 425db348bbd..00000000000
--- a/src/tools/clippy/src/docs/too_many_lines.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for functions with a large amount of lines.
-
-### Why is this bad?
-Functions with a lot of lines are harder to understand
-due to having to look at a larger amount of code to understand what the
-function is doing. Consider splitting the body of the function into
-multiple functions.
-
-### Example
-```
-fn im_too_long() {
-    println!("");
-    // ... 100 more LoC
-    println!("");
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/toplevel_ref_arg.txt b/src/tools/clippy/src/docs/toplevel_ref_arg.txt
deleted file mode 100644
index 96a9e2db8b7..00000000000
--- a/src/tools/clippy/src/docs/toplevel_ref_arg.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-### What it does
-Checks for function arguments and let bindings denoted as
-`ref`.
-
-### Why is this bad?
-The `ref` declaration makes the function take an owned
-value, but turns the argument into a reference (which means that the value
-is destroyed when exiting the function). This adds not much value: either
-take a reference type, or take an owned value and create references in the
-body.
-
-For let bindings, `let x = &foo;` is preferred over `let ref x = foo`. The
-type of `x` is more obvious with the former.
-
-### Known problems
-If the argument is dereferenced within the function,
-removing the `ref` will lead to errors. This can be fixed by removing the
-dereferences, e.g., changing `*x` to `x` within the function.
-
-### Example
-```
-fn foo(ref _x: u8) {}
-```
-
-Use instead:
-```
-fn foo(_x: &u8) {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/trailing_empty_array.txt b/src/tools/clippy/src/docs/trailing_empty_array.txt
deleted file mode 100644
index db1908cc96d..00000000000
--- a/src/tools/clippy/src/docs/trailing_empty_array.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Displays a warning when a struct with a trailing zero-sized array is declared without a `repr` attribute.
-
-### Why is this bad?
-Zero-sized arrays aren't very useful in Rust itself, so such a struct is likely being created to pass to C code or in some other situation where control over memory layout matters (for example, in conjunction with manual allocation to make it easy to compute the offset of the array). Either way, `#[repr(C)]` (or another `repr` attribute) is needed.
-
-### Example
-```
-struct RarelyUseful {
-    some_field: u32,
-    last: [u32; 0],
-}
-```
-
-Use instead:
-```
-#[repr(C)]
-struct MoreOftenUseful {
-    some_field: usize,
-    last: [u32; 0],
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/trait_duplication_in_bounds.txt b/src/tools/clippy/src/docs/trait_duplication_in_bounds.txt
deleted file mode 100644
index 509736bb364..00000000000
--- a/src/tools/clippy/src/docs/trait_duplication_in_bounds.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-### What it does
-Checks for cases where generics are being used and multiple
-syntax specifications for trait bounds are used simultaneously.
-
-### Why is this bad?
-Duplicate bounds makes the code
-less readable than specifying them only once.
-
-### Example
-```
-fn func<T: Clone + Default>(arg: T) where T: Clone + Default {}
-```
-
-Use instead:
-```
-fn func<T: Clone + Default>(arg: T) {}
-
-// or
-
-fn func<T>(arg: T) where T: Clone + Default {}
-```
-
-```
-fn foo<T: Default + Default>(bar: T) {}
-```
-Use instead:
-```
-fn foo<T: Default>(bar: T) {}
-```
-
-```
-fn foo<T>(bar: T) where T: Default + Default {}
-```
-Use instead:
-```
-fn foo<T>(bar: T) where T: Default {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/transmute_bytes_to_str.txt b/src/tools/clippy/src/docs/transmute_bytes_to_str.txt
deleted file mode 100644
index 75889b9c73a..00000000000
--- a/src/tools/clippy/src/docs/transmute_bytes_to_str.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for transmutes from a `&[u8]` to a `&str`.
-
-### Why is this bad?
-Not every byte slice is a valid UTF-8 string.
-
-### Known problems
-- [`from_utf8`] which this lint suggests using is slower than `transmute`
-as it needs to validate the input.
-If you are certain that the input is always a valid UTF-8,
-use [`from_utf8_unchecked`] which is as fast as `transmute`
-but has a semantically meaningful name.
-- You might want to handle errors returned from [`from_utf8`] instead of calling `unwrap`.
-
-[`from_utf8`]: https://doc.rust-lang.org/std/str/fn.from_utf8.html
-[`from_utf8_unchecked`]: https://doc.rust-lang.org/std/str/fn.from_utf8_unchecked.html
-
-### Example
-```
-let b: &[u8] = &[1_u8, 2_u8];
-unsafe {
-    let _: &str = std::mem::transmute(b); // where b: &[u8]
-}
-
-// should be:
-let _ = std::str::from_utf8(b).unwrap();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/transmute_float_to_int.txt b/src/tools/clippy/src/docs/transmute_float_to_int.txt
deleted file mode 100644
index 1877e5a465a..00000000000
--- a/src/tools/clippy/src/docs/transmute_float_to_int.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for transmutes from a float to an integer.
-
-### Why is this bad?
-Transmutes are dangerous and error-prone, whereas `to_bits` is intuitive
-and safe.
-
-### Example
-```
-unsafe {
-    let _: u32 = std::mem::transmute(1f32);
-}
-
-// should be:
-let _: u32 = 1f32.to_bits();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/transmute_int_to_bool.txt b/src/tools/clippy/src/docs/transmute_int_to_bool.txt
deleted file mode 100644
index 07c10f8d0bc..00000000000
--- a/src/tools/clippy/src/docs/transmute_int_to_bool.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for transmutes from an integer to a `bool`.
-
-### Why is this bad?
-This might result in an invalid in-memory representation of a `bool`.
-
-### Example
-```
-let x = 1_u8;
-unsafe {
-    let _: bool = std::mem::transmute(x); // where x: u8
-}
-
-// should be:
-let _: bool = x != 0;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/transmute_int_to_char.txt b/src/tools/clippy/src/docs/transmute_int_to_char.txt
deleted file mode 100644
index 836d22d3f99..00000000000
--- a/src/tools/clippy/src/docs/transmute_int_to_char.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for transmutes from an integer to a `char`.
-
-### Why is this bad?
-Not every integer is a Unicode scalar value.
-
-### Known problems
-- [`from_u32`] which this lint suggests using is slower than `transmute`
-as it needs to validate the input.
-If you are certain that the input is always a valid Unicode scalar value,
-use [`from_u32_unchecked`] which is as fast as `transmute`
-but has a semantically meaningful name.
-- You might want to handle `None` returned from [`from_u32`] instead of calling `unwrap`.
-
-[`from_u32`]: https://doc.rust-lang.org/std/char/fn.from_u32.html
-[`from_u32_unchecked`]: https://doc.rust-lang.org/std/char/fn.from_u32_unchecked.html
-
-### Example
-```
-let x = 1_u32;
-unsafe {
-    let _: char = std::mem::transmute(x); // where x: u32
-}
-
-// should be:
-let _ = std::char::from_u32(x).unwrap();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/transmute_int_to_float.txt b/src/tools/clippy/src/docs/transmute_int_to_float.txt
deleted file mode 100644
index 75cdc62e972..00000000000
--- a/src/tools/clippy/src/docs/transmute_int_to_float.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for transmutes from an integer to a float.
-
-### Why is this bad?
-Transmutes are dangerous and error-prone, whereas `from_bits` is intuitive
-and safe.
-
-### Example
-```
-unsafe {
-    let _: f32 = std::mem::transmute(1_u32); // where x: u32
-}
-
-// should be:
-let _: f32 = f32::from_bits(1_u32);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/transmute_num_to_bytes.txt b/src/tools/clippy/src/docs/transmute_num_to_bytes.txt
deleted file mode 100644
index a2c39a1b947..00000000000
--- a/src/tools/clippy/src/docs/transmute_num_to_bytes.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for transmutes from a number to an array of `u8`
-
-### Why this is bad?
-Transmutes are dangerous and error-prone, whereas `to_ne_bytes`
-is intuitive and safe.
-
-### Example
-```
-unsafe {
-    let x: [u8; 8] = std::mem::transmute(1i64);
-}
-
-// should be
-let x: [u8; 8] = 0i64.to_ne_bytes();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/transmute_ptr_to_ptr.txt b/src/tools/clippy/src/docs/transmute_ptr_to_ptr.txt
deleted file mode 100644
index 65777db9861..00000000000
--- a/src/tools/clippy/src/docs/transmute_ptr_to_ptr.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for transmutes from a pointer to a pointer, or
-from a reference to a reference.
-
-### Why is this bad?
-Transmutes are dangerous, and these can instead be
-written as casts.
-
-### Example
-```
-let ptr = &1u32 as *const u32;
-unsafe {
-    // pointer-to-pointer transmute
-    let _: *const f32 = std::mem::transmute(ptr);
-    // ref-ref transmute
-    let _: &f32 = std::mem::transmute(&1u32);
-}
-// These can be respectively written:
-let _ = ptr as *const f32;
-let _ = unsafe{ &*(&1u32 as *const u32 as *const f32) };
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/transmute_ptr_to_ref.txt b/src/tools/clippy/src/docs/transmute_ptr_to_ref.txt
deleted file mode 100644
index aca550f5036..00000000000
--- a/src/tools/clippy/src/docs/transmute_ptr_to_ref.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Checks for transmutes from a pointer to a reference.
-
-### Why is this bad?
-This can always be rewritten with `&` and `*`.
-
-### Known problems
-- `mem::transmute` in statics and constants is stable from Rust 1.46.0,
-while dereferencing raw pointer is not stable yet.
-If you need to do this in those places,
-you would have to use `transmute` instead.
-
-### Example
-```
-unsafe {
-    let _: &T = std::mem::transmute(p); // where p: *const T
-}
-
-// can be written:
-let _: &T = &*p;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/transmute_undefined_repr.txt b/src/tools/clippy/src/docs/transmute_undefined_repr.txt
deleted file mode 100644
index 5ee6aaf4ca9..00000000000
--- a/src/tools/clippy/src/docs/transmute_undefined_repr.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for transmutes between types which do not have a representation defined relative to
-each other.
-
-### Why is this bad?
-The results of such a transmute are not defined.
-
-### Known problems
-This lint has had multiple problems in the past and was moved to `nursery`. See issue
-[#8496](https://github.com/rust-lang/rust-clippy/issues/8496) for more details.
-
-### Example
-```
-struct Foo<T>(u32, T);
-let _ = unsafe { core::mem::transmute::<Foo<u32>, Foo<i32>>(Foo(0u32, 0u32)) };
-```
-Use instead:
-```
-#[repr(C)]
-struct Foo<T>(u32, T);
-let _ = unsafe { core::mem::transmute::<Foo<u32>, Foo<i32>>(Foo(0u32, 0u32)) };
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/transmutes_expressible_as_ptr_casts.txt b/src/tools/clippy/src/docs/transmutes_expressible_as_ptr_casts.txt
deleted file mode 100644
index b68a8cda9c7..00000000000
--- a/src/tools/clippy/src/docs/transmutes_expressible_as_ptr_casts.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Checks for transmutes that could be a pointer cast.
-
-### Why is this bad?
-Readability. The code tricks people into thinking that
-something complex is going on.
-
-### Example
-
-```
-unsafe { std::mem::transmute::<*const [i32], *const [u16]>(p) };
-```
-Use instead:
-```
-p as *const [u16];
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/transmuting_null.txt b/src/tools/clippy/src/docs/transmuting_null.txt
deleted file mode 100644
index f8bacfc0b90..00000000000
--- a/src/tools/clippy/src/docs/transmuting_null.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for transmute calls which would receive a null pointer.
-
-### Why is this bad?
-Transmuting a null pointer is undefined behavior.
-
-### Known problems
-Not all cases can be detected at the moment of this writing.
-For example, variables which hold a null pointer and are then fed to a `transmute`
-call, aren't detectable yet.
-
-### Example
-```
-let null_ref: &u64 = unsafe { std::mem::transmute(0 as *const u64) };
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/trim_split_whitespace.txt b/src/tools/clippy/src/docs/trim_split_whitespace.txt
deleted file mode 100644
index f7e3e7858f9..00000000000
--- a/src/tools/clippy/src/docs/trim_split_whitespace.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Warns about calling `str::trim` (or variants) before `str::split_whitespace`.
-
-### Why is this bad?
-`split_whitespace` already ignores leading and trailing whitespace.
-
-### Example
-```
-" A B C ".trim().split_whitespace();
-```
-Use instead:
-```
-" A B C ".split_whitespace();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/trivial_regex.txt b/src/tools/clippy/src/docs/trivial_regex.txt
deleted file mode 100644
index f71d667fd77..00000000000
--- a/src/tools/clippy/src/docs/trivial_regex.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for trivial [regex](https://crates.io/crates/regex)
-creation (with `Regex::new`, `RegexBuilder::new`, or `RegexSet::new`).
-
-### Why is this bad?
-Matching the regex can likely be replaced by `==` or
-`str::starts_with`, `str::ends_with` or `std::contains` or other `str`
-methods.
-
-### Known problems
-If the same regex is going to be applied to multiple
-inputs, the precomputations done by `Regex` construction can give
-significantly better performance than any of the `str`-based methods.
-
-### Example
-```
-Regex::new("^foobar")
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/trivially_copy_pass_by_ref.txt b/src/tools/clippy/src/docs/trivially_copy_pass_by_ref.txt
deleted file mode 100644
index f54cce5e2bd..00000000000
--- a/src/tools/clippy/src/docs/trivially_copy_pass_by_ref.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-### What it does
-Checks for functions taking arguments by reference, where
-the argument type is `Copy` and small enough to be more efficient to always
-pass by value.
-
-### Why is this bad?
-In many calling conventions instances of structs will
-be passed through registers if they fit into two or less general purpose
-registers.
-
-### Known problems
-This lint is target register size dependent, it is
-limited to 32-bit to try and reduce portability problems between 32 and
-64-bit, but if you are compiling for 8 or 16-bit targets then the limit
-will be different.
-
-The configuration option `trivial_copy_size_limit` can be set to override
-this limit for a project.
-
-This lint attempts to allow passing arguments by reference if a reference
-to that argument is returned. This is implemented by comparing the lifetime
-of the argument and return value for equality. However, this can cause
-false positives in cases involving multiple lifetimes that are bounded by
-each other.
-
-Also, it does not take account of other similar cases where getting memory addresses
-matters; namely, returning the pointer to the argument in question,
-and passing the argument, as both references and pointers,
-to a function that needs the memory address. For further details, refer to
-[this issue](https://github.com/rust-lang/rust-clippy/issues/5953)
-that explains a real case in which this false positive
-led to an **undefined behavior** introduced with unsafe code.
-
-### Example
-
-```
-fn foo(v: &u32) {}
-```
-
-Use instead:
-```
-fn foo(v: u32) {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/try_err.txt b/src/tools/clippy/src/docs/try_err.txt
deleted file mode 100644
index e3d4ef3a09d..00000000000
--- a/src/tools/clippy/src/docs/try_err.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-### What it does
-Checks for usages of `Err(x)?`.
-
-### Why is this bad?
-The `?` operator is designed to allow calls that
-can fail to be easily chained. For example, `foo()?.bar()` or
-`foo(bar()?)`. Because `Err(x)?` can't be used that way (it will
-always return), it is more clear to write `return Err(x)`.
-
-### Example
-```
-fn foo(fail: bool) -> Result<i32, String> {
-    if fail {
-      Err("failed")?;
-    }
-    Ok(0)
-}
-```
-Could be written:
-
-```
-fn foo(fail: bool) -> Result<i32, String> {
-    if fail {
-      return Err("failed".into());
-    }
-    Ok(0)
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/type_complexity.txt b/src/tools/clippy/src/docs/type_complexity.txt
deleted file mode 100644
index 69cd8750050..00000000000
--- a/src/tools/clippy/src/docs/type_complexity.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Checks for types used in structs, parameters and `let`
-declarations above a certain complexity threshold.
-
-### Why is this bad?
-Too complex types make the code less readable. Consider
-using a `type` definition to simplify them.
-
-### Example
-```
-struct Foo {
-    inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>,
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/type_repetition_in_bounds.txt b/src/tools/clippy/src/docs/type_repetition_in_bounds.txt
deleted file mode 100644
index 18ed372fd13..00000000000
--- a/src/tools/clippy/src/docs/type_repetition_in_bounds.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-This lint warns about unnecessary type repetitions in trait bounds
-
-### Why is this bad?
-Repeating the type for every bound makes the code
-less readable than combining the bounds
-
-### Example
-```
-pub fn foo<T>(t: T) where T: Copy, T: Clone {}
-```
-
-Use instead:
-```
-pub fn foo<T>(t: T) where T: Copy + Clone {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/undocumented_unsafe_blocks.txt b/src/tools/clippy/src/docs/undocumented_unsafe_blocks.txt
deleted file mode 100644
index f3af4753c5f..00000000000
--- a/src/tools/clippy/src/docs/undocumented_unsafe_blocks.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-### What it does
-Checks for `unsafe` blocks and impls without a `// SAFETY: ` comment
-explaining why the unsafe operations performed inside
-the block are safe.
-
-Note the comment must appear on the line(s) preceding the unsafe block
-with nothing appearing in between. The following is ok:
-```
-foo(
-    // SAFETY:
-    // This is a valid safety comment
-    unsafe { *x }
-)
-```
-But neither of these are:
-```
-// SAFETY:
-// This is not a valid safety comment
-foo(
-    /* SAFETY: Neither is this */ unsafe { *x },
-);
-```
-
-### Why is this bad?
-Undocumented unsafe blocks and impls can make it difficult to
-read and maintain code, as well as uncover unsoundness
-and bugs.
-
-### Example
-```
-use std::ptr::NonNull;
-let a = &mut 42;
-
-let ptr = unsafe { NonNull::new_unchecked(a) };
-```
-Use instead:
-```
-use std::ptr::NonNull;
-let a = &mut 42;
-
-// SAFETY: references are guaranteed to be non-null.
-let ptr = unsafe { NonNull::new_unchecked(a) };
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/undropped_manually_drops.txt b/src/tools/clippy/src/docs/undropped_manually_drops.txt
deleted file mode 100644
index 85e3ec56653..00000000000
--- a/src/tools/clippy/src/docs/undropped_manually_drops.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Prevents the safe `std::mem::drop` function from being called on `std::mem::ManuallyDrop`.
-
-### Why is this bad?
-The safe `drop` function does not drop the inner value of a `ManuallyDrop`.
-
-### Known problems
-Does not catch cases if the user binds `std::mem::drop`
-to a different name and calls it that way.
-
-### Example
-```
-struct S;
-drop(std::mem::ManuallyDrop::new(S));
-```
-Use instead:
-```
-struct S;
-unsafe {
-    std::mem::ManuallyDrop::drop(&mut std::mem::ManuallyDrop::new(S));
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unicode_not_nfc.txt b/src/tools/clippy/src/docs/unicode_not_nfc.txt
deleted file mode 100644
index c660c51dadb..00000000000
--- a/src/tools/clippy/src/docs/unicode_not_nfc.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for string literals that contain Unicode in a form
-that is not equal to its
-[NFC-recomposition](http://www.unicode.org/reports/tr15/#Norm_Forms).
-
-### Why is this bad?
-If such a string is compared to another, the results
-may be surprising.
-
-### Example
-You may not see it, but "à"" and "à"" aren't the same string. The
-former when escaped is actually `"a\u{300}"` while the latter is `"\u{e0}"`.
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unimplemented.txt b/src/tools/clippy/src/docs/unimplemented.txt
deleted file mode 100644
index 7095594fb2e..00000000000
--- a/src/tools/clippy/src/docs/unimplemented.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-### What it does
-Checks for usage of `unimplemented!`.
-
-### Why is this bad?
-This macro should not be present in production code
-
-### Example
-```
-unimplemented!();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/uninit_assumed_init.txt b/src/tools/clippy/src/docs/uninit_assumed_init.txt
deleted file mode 100644
index cca24093d40..00000000000
--- a/src/tools/clippy/src/docs/uninit_assumed_init.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-### What it does
-Checks for `MaybeUninit::uninit().assume_init()`.
-
-### Why is this bad?
-For most types, this is undefined behavior.
-
-### Known problems
-For now, we accept empty tuples and tuples / arrays
-of `MaybeUninit`. There may be other types that allow uninitialized
-data, but those are not yet rigorously defined.
-
-### Example
-```
-// Beware the UB
-use std::mem::MaybeUninit;
-
-let _: usize = unsafe { MaybeUninit::uninit().assume_init() };
-```
-
-Note that the following is OK:
-
-```
-use std::mem::MaybeUninit;
-
-let _: [MaybeUninit<bool>; 5] = unsafe {
-    MaybeUninit::uninit().assume_init()
-};
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/uninit_vec.txt b/src/tools/clippy/src/docs/uninit_vec.txt
deleted file mode 100644
index cd50afe78f6..00000000000
--- a/src/tools/clippy/src/docs/uninit_vec.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-### What it does
-Checks for `set_len()` call that creates `Vec` with uninitialized elements.
-This is commonly caused by calling `set_len()` right after allocating or
-reserving a buffer with `new()`, `default()`, `with_capacity()`, or `reserve()`.
-
-### Why is this bad?
-It creates a `Vec` with uninitialized data, which leads to
-undefined behavior with most safe operations. Notably, uninitialized
-`Vec<u8>` must not be used with generic `Read`.
-
-Moreover, calling `set_len()` on a `Vec` created with `new()` or `default()`
-creates out-of-bound values that lead to heap memory corruption when used.
-
-### Known Problems
-This lint only checks directly adjacent statements.
-
-### Example
-```
-let mut vec: Vec<u8> = Vec::with_capacity(1000);
-unsafe { vec.set_len(1000); }
-reader.read(&mut vec); // undefined behavior!
-```
-
-### How to fix?
-1. Use an initialized buffer:
-   ```rust,ignore
-   let mut vec: Vec<u8> = vec![0; 1000];
-   reader.read(&mut vec);
-   ```
-2. Wrap the content in `MaybeUninit`:
-   ```rust,ignore
-   let mut vec: Vec<MaybeUninit<T>> = Vec::with_capacity(1000);
-   vec.set_len(1000);  // `MaybeUninit` can be uninitialized
-   ```
-3. If you are on 1.60.0 or later, `Vec::spare_capacity_mut()` is available:
-   ```rust,ignore
-   let mut vec: Vec<u8> = Vec::with_capacity(1000);
-   let remaining = vec.spare_capacity_mut();  // `&mut [MaybeUninit<u8>]`
-   // perform initialization with `remaining`
-   vec.set_len(...);  // Safe to call `set_len()` on initialized part
-   ```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/uninlined_format_args.txt b/src/tools/clippy/src/docs/uninlined_format_args.txt
deleted file mode 100644
index 3d2966c84db..00000000000
--- a/src/tools/clippy/src/docs/uninlined_format_args.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-### What it does
-Detect when a variable is not inlined in a format string,
-and suggests to inline it.
-
-### Why is this bad?
-Non-inlined code is slightly more difficult to read and understand,
-as it requires arguments to be matched against the format string.
-The inlined syntax, where allowed, is simpler.
-
-### Example
-```
-format!("{}", var);
-format!("{v:?}", v = var);
-format!("{0} {0}", var);
-format!("{0:1$}", var, width);
-format!("{:.*}", prec, var);
-```
-Use instead:
-```
-format!("{var}");
-format!("{var:?}");
-format!("{var} {var}");
-format!("{var:width$}");
-format!("{var:.prec$}");
-```
-
-### Known Problems
-
-There may be a false positive if the format string is expanded from certain proc macros:
-
-```
-println!(indoc!("{}"), var);
-```
-
-If a format string contains a numbered argument that cannot be inlined
-nothing will be suggested, e.g. `println!("{0}={1}", var, 1+2)`.
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unit_arg.txt b/src/tools/clippy/src/docs/unit_arg.txt
deleted file mode 100644
index eb83403bb27..00000000000
--- a/src/tools/clippy/src/docs/unit_arg.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-### What it does
-Checks for passing a unit value as an argument to a function without using a
-unit literal (`()`).
-
-### Why is this bad?
-This is likely the result of an accidental semicolon.
-
-### Example
-```
-foo({
-    let a = bar();
-    baz(a);
-})
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unit_cmp.txt b/src/tools/clippy/src/docs/unit_cmp.txt
deleted file mode 100644
index 6f3d62010dc..00000000000
--- a/src/tools/clippy/src/docs/unit_cmp.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-### What it does
-Checks for comparisons to unit. This includes all binary
-comparisons (like `==` and `<`) and asserts.
-
-### Why is this bad?
-Unit is always equal to itself, and thus is just a
-clumsily written constant. Mostly this happens when someone accidentally
-adds semicolons at the end of the operands.
-
-### Example
-```
-if {
-    foo();
-} == {
-    bar();
-} {
-    baz();
-}
-```
-is equal to
-```
-{
-    foo();
-    bar();
-    baz();
-}
-```
-
-For asserts:
-```
-assert_eq!({ foo(); }, { bar(); });
-```
-will always succeed
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unit_hash.txt b/src/tools/clippy/src/docs/unit_hash.txt
deleted file mode 100644
index a22d2994602..00000000000
--- a/src/tools/clippy/src/docs/unit_hash.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Detects `().hash(_)`.
-
-### Why is this bad?
-Hashing a unit value doesn't do anything as the implementation of `Hash` for `()` is a no-op.
-
-### Example
-```
-match my_enum {
-	Empty => ().hash(&mut state),
-	WithValue(x) => x.hash(&mut state),
-}
-```
-Use instead:
-```
-match my_enum {
-	Empty => 0_u8.hash(&mut state),
-	WithValue(x) => x.hash(&mut state),
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unit_return_expecting_ord.txt b/src/tools/clippy/src/docs/unit_return_expecting_ord.txt
deleted file mode 100644
index 781feac5afc..00000000000
--- a/src/tools/clippy/src/docs/unit_return_expecting_ord.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for functions that expect closures of type
-Fn(...) -> Ord where the implemented closure returns the unit type.
-The lint also suggests to remove the semi-colon at the end of the statement if present.
-
-### Why is this bad?
-Likely, returning the unit type is unintentional, and
-could simply be caused by an extra semi-colon. Since () implements Ord
-it doesn't cause a compilation error.
-This is the same reasoning behind the unit_cmp lint.
-
-### Known problems
-If returning unit is intentional, then there is no
-way of specifying this without triggering needless_return lint
-
-### Example
-```
-let mut twins = vec!((1, 1), (2, 2));
-twins.sort_by_key(|x| { x.1; });
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnecessary_cast.txt b/src/tools/clippy/src/docs/unnecessary_cast.txt
deleted file mode 100644
index 603f2606099..00000000000
--- a/src/tools/clippy/src/docs/unnecessary_cast.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for casts to the same type, casts of int literals to integer types
-and casts of float literals to float types.
-
-### Why is this bad?
-It's just unnecessary.
-
-### Example
-```
-let _ = 2i32 as i32;
-let _ = 0.5 as f32;
-```
-
-Better:
-
-```
-let _ = 2_i32;
-let _ = 0.5_f32;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnecessary_filter_map.txt b/src/tools/clippy/src/docs/unnecessary_filter_map.txt
deleted file mode 100644
index b19341ecf66..00000000000
--- a/src/tools/clippy/src/docs/unnecessary_filter_map.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for `filter_map` calls that could be replaced by `filter` or `map`.
-More specifically it checks if the closure provided is only performing one of the
-filter or map operations and suggests the appropriate option.
-
-### Why is this bad?
-Complexity. The intent is also clearer if only a single
-operation is being performed.
-
-### Example
-```
-let _ = (0..3).filter_map(|x| if x > 2 { Some(x) } else { None });
-
-// As there is no transformation of the argument this could be written as:
-let _ = (0..3).filter(|&x| x > 2);
-```
-
-```
-let _ = (0..4).filter_map(|x| Some(x + 1));
-
-// As there is no conditional check on the argument this could be written as:
-let _ = (0..4).map(|x| x + 1);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnecessary_find_map.txt b/src/tools/clippy/src/docs/unnecessary_find_map.txt
deleted file mode 100644
index f9444dc48ad..00000000000
--- a/src/tools/clippy/src/docs/unnecessary_find_map.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for `find_map` calls that could be replaced by `find` or `map`. More
-specifically it checks if the closure provided is only performing one of the
-find or map operations and suggests the appropriate option.
-
-### Why is this bad?
-Complexity. The intent is also clearer if only a single
-operation is being performed.
-
-### Example
-```
-let _ = (0..3).find_map(|x| if x > 2 { Some(x) } else { None });
-
-// As there is no transformation of the argument this could be written as:
-let _ = (0..3).find(|&x| x > 2);
-```
-
-```
-let _ = (0..4).find_map(|x| Some(x + 1));
-
-// As there is no conditional check on the argument this could be written as:
-let _ = (0..4).map(|x| x + 1).next();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnecessary_fold.txt b/src/tools/clippy/src/docs/unnecessary_fold.txt
deleted file mode 100644
index e1b0e65f519..00000000000
--- a/src/tools/clippy/src/docs/unnecessary_fold.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for using `fold` when a more succinct alternative exists.
-Specifically, this checks for `fold`s which could be replaced by `any`, `all`,
-`sum` or `product`.
-
-### Why is this bad?
-Readability.
-
-### Example
-```
-(0..3).fold(false, |acc, x| acc || x > 2);
-```
-
-Use instead:
-```
-(0..3).any(|x| x > 2);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnecessary_join.txt b/src/tools/clippy/src/docs/unnecessary_join.txt
deleted file mode 100644
index ee4e78601f8..00000000000
--- a/src/tools/clippy/src/docs/unnecessary_join.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Checks for use of `.collect::<Vec<String>>().join("")` on iterators.
-
-### Why is this bad?
-`.collect::<String>()` is more concise and might be more performant
-
-### Example
-```
-let vector = vec!["hello",  "world"];
-let output = vector.iter().map(|item| item.to_uppercase()).collect::<Vec<String>>().join("");
-println!("{}", output);
-```
-The correct use would be:
-```
-let vector = vec!["hello",  "world"];
-let output = vector.iter().map(|item| item.to_uppercase()).collect::<String>();
-println!("{}", output);
-```
-### Known problems
-While `.collect::<String>()` is sometimes more performant, there are cases where
-using `.collect::<String>()` over `.collect::<Vec<String>>().join("")`
-will prevent loop unrolling and will result in a negative performance impact.
-
-Additionally, differences have been observed between aarch64 and x86_64 assembly output,
-with aarch64 tending to producing faster assembly in more cases when using `.collect::<String>()`
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnecessary_lazy_evaluations.txt b/src/tools/clippy/src/docs/unnecessary_lazy_evaluations.txt
deleted file mode 100644
index 208188ce971..00000000000
--- a/src/tools/clippy/src/docs/unnecessary_lazy_evaluations.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-### What it does
-As the counterpart to `or_fun_call`, this lint looks for unnecessary
-lazily evaluated closures on `Option` and `Result`.
-
-This lint suggests changing the following functions, when eager evaluation results in
-simpler code:
- - `unwrap_or_else` to `unwrap_or`
- - `and_then` to `and`
- - `or_else` to `or`
- - `get_or_insert_with` to `get_or_insert`
- - `ok_or_else` to `ok_or`
-
-### Why is this bad?
-Using eager evaluation is shorter and simpler in some cases.
-
-### Known problems
-It is possible, but not recommended for `Deref` and `Index` to have
-side effects. Eagerly evaluating them can change the semantics of the program.
-
-### Example
-```
-// example code where clippy issues a warning
-let opt: Option<u32> = None;
-
-opt.unwrap_or_else(|| 42);
-```
-Use instead:
-```
-let opt: Option<u32> = None;
-
-opt.unwrap_or(42);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnecessary_mut_passed.txt b/src/tools/clippy/src/docs/unnecessary_mut_passed.txt
deleted file mode 100644
index 2f8bdd113df..00000000000
--- a/src/tools/clippy/src/docs/unnecessary_mut_passed.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Detects passing a mutable reference to a function that only
-requires an immutable reference.
-
-### Why is this bad?
-The mutable reference rules out all other references to
-the value. Also the code misleads about the intent of the call site.
-
-### Example
-```
-vec.push(&mut value);
-```
-
-Use instead:
-```
-vec.push(&value);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnecessary_operation.txt b/src/tools/clippy/src/docs/unnecessary_operation.txt
deleted file mode 100644
index 7f455e264cb..00000000000
--- a/src/tools/clippy/src/docs/unnecessary_operation.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for expression statements that can be reduced to a
-sub-expression.
-
-### Why is this bad?
-Expressions by themselves often have no side-effects.
-Having such expressions reduces readability.
-
-### Example
-```
-compute_array()[0];
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnecessary_owned_empty_strings.txt b/src/tools/clippy/src/docs/unnecessary_owned_empty_strings.txt
deleted file mode 100644
index 8cd9fba603e..00000000000
--- a/src/tools/clippy/src/docs/unnecessary_owned_empty_strings.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-
-Detects cases of owned empty strings being passed as an argument to a function expecting `&str`
-
-### Why is this bad?
-
-This results in longer and less readable code
-
-### Example
-```
-vec!["1", "2", "3"].join(&String::new());
-```
-Use instead:
-```
-vec!["1", "2", "3"].join("");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnecessary_self_imports.txt b/src/tools/clippy/src/docs/unnecessary_self_imports.txt
deleted file mode 100644
index b909cd5a76d..00000000000
--- a/src/tools/clippy/src/docs/unnecessary_self_imports.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for imports ending in `::{self}`.
-
-### Why is this bad?
-In most cases, this can be written much more cleanly by omitting `::{self}`.
-
-### Known problems
-Removing `::{self}` will cause any non-module items at the same path to also be imported.
-This might cause a naming conflict (https://github.com/rust-lang/rustfmt/issues/3568). This lint makes no attempt
-to detect this scenario and that is why it is a restriction lint.
-
-### Example
-```
-use std::io::{self};
-```
-Use instead:
-```
-use std::io;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnecessary_sort_by.txt b/src/tools/clippy/src/docs/unnecessary_sort_by.txt
deleted file mode 100644
index 6913b62c48e..00000000000
--- a/src/tools/clippy/src/docs/unnecessary_sort_by.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-### What it does
-Detects uses of `Vec::sort_by` passing in a closure
-which compares the two arguments, either directly or indirectly.
-
-### Why is this bad?
-It is more clear to use `Vec::sort_by_key` (or `Vec::sort` if
-possible) than to use `Vec::sort_by` and a more complicated
-closure.
-
-### Known problems
-If the suggested `Vec::sort_by_key` uses Reverse and it isn't already
-imported by a use statement, then it will need to be added manually.
-
-### Example
-```
-vec.sort_by(|a, b| a.foo().cmp(&b.foo()));
-```
-Use instead:
-```
-vec.sort_by_key(|a| a.foo());
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnecessary_to_owned.txt b/src/tools/clippy/src/docs/unnecessary_to_owned.txt
deleted file mode 100644
index 5d4213bdaf8..00000000000
--- a/src/tools/clippy/src/docs/unnecessary_to_owned.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for unnecessary calls to [`ToOwned::to_owned`](https://doc.rust-lang.org/std/borrow/trait.ToOwned.html#tymethod.to_owned)
-and other `to_owned`-like functions.
-
-### Why is this bad?
-The unnecessary calls result in useless allocations.
-
-### Known problems
-`unnecessary_to_owned` can falsely trigger if `IntoIterator::into_iter` is applied to an
-owned copy of a resource and the resource is later used mutably. See
-[#8148](https://github.com/rust-lang/rust-clippy/issues/8148).
-
-### Example
-```
-let path = std::path::Path::new("x");
-foo(&path.to_string_lossy().to_string());
-fn foo(s: &str) {}
-```
-Use instead:
-```
-let path = std::path::Path::new("x");
-foo(&path.to_string_lossy());
-fn foo(s: &str) {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnecessary_unwrap.txt b/src/tools/clippy/src/docs/unnecessary_unwrap.txt
deleted file mode 100644
index 50ae845bb44..00000000000
--- a/src/tools/clippy/src/docs/unnecessary_unwrap.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for calls of `unwrap[_err]()` that cannot fail.
-
-### Why is this bad?
-Using `if let` or `match` is more idiomatic.
-
-### Example
-```
-if option.is_some() {
-    do_something_with(option.unwrap())
-}
-```
-
-Could be written:
-
-```
-if let Some(value) = option {
-    do_something_with(value)
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnecessary_wraps.txt b/src/tools/clippy/src/docs/unnecessary_wraps.txt
deleted file mode 100644
index c0a23d49288..00000000000
--- a/src/tools/clippy/src/docs/unnecessary_wraps.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-### What it does
-Checks for private functions that only return `Ok` or `Some`.
-
-### Why is this bad?
-It is not meaningful to wrap values when no `None` or `Err` is returned.
-
-### Known problems
-There can be false positives if the function signature is designed to
-fit some external requirement.
-
-### Example
-```
-fn get_cool_number(a: bool, b: bool) -> Option<i32> {
-    if a && b {
-        return Some(50);
-    }
-    if a {
-        Some(0)
-    } else {
-        Some(10)
-    }
-}
-```
-Use instead:
-```
-fn get_cool_number(a: bool, b: bool) -> i32 {
-    if a && b {
-        return 50;
-    }
-    if a {
-        0
-    } else {
-        10
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unneeded_field_pattern.txt b/src/tools/clippy/src/docs/unneeded_field_pattern.txt
deleted file mode 100644
index 3cd00a0f3e3..00000000000
--- a/src/tools/clippy/src/docs/unneeded_field_pattern.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for structure field patterns bound to wildcards.
-
-### Why is this bad?
-Using `..` instead is shorter and leaves the focus on
-the fields that are actually bound.
-
-### Example
-```
-let f = Foo { a: 0, b: 0, c: 0 };
-
-match f {
-    Foo { a: _, b: 0, .. } => {},
-    Foo { a: _, b: _, c: _ } => {},
-}
-```
-
-Use instead:
-```
-let f = Foo { a: 0, b: 0, c: 0 };
-
-match f {
-    Foo { b: 0, .. } => {},
-    Foo { .. } => {},
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unneeded_wildcard_pattern.txt b/src/tools/clippy/src/docs/unneeded_wildcard_pattern.txt
deleted file mode 100644
index 817061efd16..00000000000
--- a/src/tools/clippy/src/docs/unneeded_wildcard_pattern.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-### What it does
-Checks for tuple patterns with a wildcard
-pattern (`_`) is next to a rest pattern (`..`).
-
-_NOTE_: While `_, ..` means there is at least one element left, `..`
-means there are 0 or more elements left. This can make a difference
-when refactoring, but shouldn't result in errors in the refactored code,
-since the wildcard pattern isn't used anyway.
-
-### Why is this bad?
-The wildcard pattern is unneeded as the rest pattern
-can match that element as well.
-
-### Example
-```
-match t {
-    TupleStruct(0, .., _) => (),
-    _ => (),
-}
-```
-
-Use instead:
-```
-match t {
-    TupleStruct(0, ..) => (),
-    _ => (),
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unnested_or_patterns.txt b/src/tools/clippy/src/docs/unnested_or_patterns.txt
deleted file mode 100644
index 49c45d4ee5e..00000000000
--- a/src/tools/clippy/src/docs/unnested_or_patterns.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for unnested or-patterns, e.g., `Some(0) | Some(2)` and
-suggests replacing the pattern with a nested one, `Some(0 | 2)`.
-
-Another way to think of this is that it rewrites patterns in
-*disjunctive normal form (DNF)* into *conjunctive normal form (CNF)*.
-
-### Why is this bad?
-In the example above, `Some` is repeated, which unnecessarily complicates the pattern.
-
-### Example
-```
-fn main() {
-    if let Some(0) | Some(2) = Some(0) {}
-}
-```
-Use instead:
-```
-fn main() {
-    if let Some(0 | 2) = Some(0) {}
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unreachable.txt b/src/tools/clippy/src/docs/unreachable.txt
deleted file mode 100644
index 10469ca7745..00000000000
--- a/src/tools/clippy/src/docs/unreachable.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-### What it does
-Checks for usage of `unreachable!`.
-
-### Why is this bad?
-This macro can cause code to panic
-
-### Example
-```
-unreachable!();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unreadable_literal.txt b/src/tools/clippy/src/docs/unreadable_literal.txt
deleted file mode 100644
index e168f90a84c..00000000000
--- a/src/tools/clippy/src/docs/unreadable_literal.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Warns if a long integral or floating-point constant does
-not contain underscores.
-
-### Why is this bad?
-Reading long numbers is difficult without separators.
-
-### Example
-```
-61864918973511
-```
-
-Use instead:
-```
-61_864_918_973_511
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unsafe_derive_deserialize.txt b/src/tools/clippy/src/docs/unsafe_derive_deserialize.txt
deleted file mode 100644
index f56c48044f4..00000000000
--- a/src/tools/clippy/src/docs/unsafe_derive_deserialize.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-### What it does
-Checks for deriving `serde::Deserialize` on a type that
-has methods using `unsafe`.
-
-### Why is this bad?
-Deriving `serde::Deserialize` will create a constructor
-that may violate invariants hold by another constructor.
-
-### Example
-```
-use serde::Deserialize;
-
-#[derive(Deserialize)]
-pub struct Foo {
-    // ..
-}
-
-impl Foo {
-    pub fn new() -> Self {
-        // setup here ..
-    }
-
-    pub unsafe fn parts() -> (&str, &str) {
-        // assumes invariants hold
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unsafe_removed_from_name.txt b/src/tools/clippy/src/docs/unsafe_removed_from_name.txt
deleted file mode 100644
index 6f55c1815dd..00000000000
--- a/src/tools/clippy/src/docs/unsafe_removed_from_name.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for imports that remove "unsafe" from an item's
-name.
-
-### Why is this bad?
-Renaming makes it less clear which traits and
-structures are unsafe.
-
-### Example
-```
-use std::cell::{UnsafeCell as TotallySafeCell};
-
-extern crate crossbeam;
-use crossbeam::{spawn_unsafe as spawn};
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unseparated_literal_suffix.txt b/src/tools/clippy/src/docs/unseparated_literal_suffix.txt
deleted file mode 100644
index d80248e34d0..00000000000
--- a/src/tools/clippy/src/docs/unseparated_literal_suffix.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Warns if literal suffixes are not separated by an
-underscore.
-To enforce unseparated literal suffix style,
-see the `separated_literal_suffix` lint.
-
-### Why is this bad?
-Suffix style should be consistent.
-
-### Example
-```
-123832i32
-```
-
-Use instead:
-```
-123832_i32
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unsound_collection_transmute.txt b/src/tools/clippy/src/docs/unsound_collection_transmute.txt
deleted file mode 100644
index 29db9258e83..00000000000
--- a/src/tools/clippy/src/docs/unsound_collection_transmute.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Checks for transmutes between collections whose
-types have different ABI, size or alignment.
-
-### Why is this bad?
-This is undefined behavior.
-
-### Known problems
-Currently, we cannot know whether a type is a
-collection, so we just lint the ones that come with `std`.
-
-### Example
-```
-// different size, therefore likely out-of-bounds memory access
-// You absolutely do not want this in your code!
-unsafe {
-    std::mem::transmute::<_, Vec<u32>>(vec![2_u16])
-};
-```
-
-You must always iterate, map and collect the values:
-
-```
-vec![2_u16].into_iter().map(u32::from).collect::<Vec<_>>();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unused_async.txt b/src/tools/clippy/src/docs/unused_async.txt
deleted file mode 100644
index 26def11aa17..00000000000
--- a/src/tools/clippy/src/docs/unused_async.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for functions that are declared `async` but have no `.await`s inside of them.
-
-### Why is this bad?
-Async functions with no async code create overhead, both mentally and computationally.
-Callers of async methods either need to be calling from an async function themselves or run it on an executor, both of which
-causes runtime overhead and hassle for the caller.
-
-### Example
-```
-async fn get_random_number() -> i64 {
-    4 // Chosen by fair dice roll. Guaranteed to be random.
-}
-let number_future = get_random_number();
-```
-
-Use instead:
-```
-fn get_random_number_improved() -> i64 {
-    4 // Chosen by fair dice roll. Guaranteed to be random.
-}
-let number_future = async { get_random_number_improved() };
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unused_format_specs.txt b/src/tools/clippy/src/docs/unused_format_specs.txt
deleted file mode 100644
index 77be3a2fb17..00000000000
--- a/src/tools/clippy/src/docs/unused_format_specs.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Detects [formatting parameters] that have no effect on the output of
-`format!()`, `println!()` or similar macros.
-
-### Why is this bad?
-Shorter format specifiers are easier to read, it may also indicate that
-an expected formatting operation such as adding padding isn't happening.
-
-### Example
-```
-println!("{:.}", 1.0);
-
-println!("not padded: {:5}", format_args!("..."));
-```
-Use instead:
-```
-println!("{}", 1.0);
-
-println!("not padded: {}", format_args!("..."));
-// OR
-println!("padded: {:5}", format!("..."));
-```
-
-[formatting parameters]: https://doc.rust-lang.org/std/fmt/index.html#formatting-parameters
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unused_io_amount.txt b/src/tools/clippy/src/docs/unused_io_amount.txt
deleted file mode 100644
index fbc4c299c7b..00000000000
--- a/src/tools/clippy/src/docs/unused_io_amount.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-### What it does
-Checks for unused written/read amount.
-
-### Why is this bad?
-`io::Write::write(_vectored)` and
-`io::Read::read(_vectored)` are not guaranteed to
-process the entire buffer. They return how many bytes were processed, which
-might be smaller
-than a given buffer's length. If you don't need to deal with
-partial-write/read, use
-`write_all`/`read_exact` instead.
-
-When working with asynchronous code (either with the `futures`
-crate or with `tokio`), a similar issue exists for
-`AsyncWriteExt::write()` and `AsyncReadExt::read()` : these
-functions are also not guaranteed to process the entire
-buffer.  Your code should either handle partial-writes/reads, or
-call the `write_all`/`read_exact` methods on those traits instead.
-
-### Known problems
-Detects only common patterns.
-
-### Examples
-```
-use std::io;
-fn foo<W: io::Write>(w: &mut W) -> io::Result<()> {
-    // must be `w.write_all(b"foo")?;`
-    w.write(b"foo")?;
-    Ok(())
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unused_peekable.txt b/src/tools/clippy/src/docs/unused_peekable.txt
deleted file mode 100644
index 268de1ce3be..00000000000
--- a/src/tools/clippy/src/docs/unused_peekable.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for the creation of a `peekable` iterator that is never `.peek()`ed
-
-### Why is this bad?
-Creating a peekable iterator without using any of its methods is likely a mistake,
-or just a leftover after a refactor.
-
-### Example
-```
-let collection = vec![1, 2, 3];
-let iter = collection.iter().peekable();
-
-for item in iter {
-    // ...
-}
-```
-
-Use instead:
-```
-let collection = vec![1, 2, 3];
-let iter = collection.iter();
-
-for item in iter {
-    // ...
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unused_rounding.txt b/src/tools/clippy/src/docs/unused_rounding.txt
deleted file mode 100644
index 70947aceee7..00000000000
--- a/src/tools/clippy/src/docs/unused_rounding.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-
-Detects cases where a whole-number literal float is being rounded, using
-the `floor`, `ceil`, or `round` methods.
-
-### Why is this bad?
-
-This is unnecessary and confusing to the reader. Doing this is probably a mistake.
-
-### Example
-```
-let x = 1f32.ceil();
-```
-Use instead:
-```
-let x = 1f32;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unused_self.txt b/src/tools/clippy/src/docs/unused_self.txt
deleted file mode 100644
index a8d0fc75989..00000000000
--- a/src/tools/clippy/src/docs/unused_self.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks methods that contain a `self` argument but don't use it
-
-### Why is this bad?
-It may be clearer to define the method as an associated function instead
-of an instance method if it doesn't require `self`.
-
-### Example
-```
-struct A;
-impl A {
-    fn method(&self) {}
-}
-```
-
-Could be written:
-
-```
-struct A;
-impl A {
-    fn method() {}
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unused_unit.txt b/src/tools/clippy/src/docs/unused_unit.txt
deleted file mode 100644
index 48d16ca6552..00000000000
--- a/src/tools/clippy/src/docs/unused_unit.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for unit (`()`) expressions that can be removed.
-
-### Why is this bad?
-Such expressions add no value, but can make the code
-less readable. Depending on formatting they can make a `break` or `return`
-statement look like a function call.
-
-### Example
-```
-fn return_unit() -> () {
-    ()
-}
-```
-is equivalent to
-```
-fn return_unit() {}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unusual_byte_groupings.txt b/src/tools/clippy/src/docs/unusual_byte_groupings.txt
deleted file mode 100644
index 9a1f132a611..00000000000
--- a/src/tools/clippy/src/docs/unusual_byte_groupings.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Warns if hexadecimal or binary literals are not grouped
-by nibble or byte.
-
-### Why is this bad?
-Negatively impacts readability.
-
-### Example
-```
-let x: u32 = 0xFFF_FFF;
-let y: u8 = 0b01_011_101;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unwrap_in_result.txt b/src/tools/clippy/src/docs/unwrap_in_result.txt
deleted file mode 100644
index 7497dd863d3..00000000000
--- a/src/tools/clippy/src/docs/unwrap_in_result.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-### What it does
-Checks for functions of type `Result` that contain `expect()` or `unwrap()`
-
-### Why is this bad?
-These functions promote recoverable errors to non-recoverable errors which may be undesirable in code bases which wish to avoid panics.
-
-### Known problems
-This can cause false positives in functions that handle both recoverable and non recoverable errors.
-
-### Example
-Before:
-```
-fn divisible_by_3(i_str: String) -> Result<(), String> {
-    let i = i_str
-        .parse::<i32>()
-        .expect("cannot divide the input by three");
-
-    if i % 3 != 0 {
-        Err("Number is not divisible by 3")?
-    }
-
-    Ok(())
-}
-```
-
-After:
-```
-fn divisible_by_3(i_str: String) -> Result<(), String> {
-    let i = i_str
-        .parse::<i32>()
-        .map_err(|e| format!("cannot divide the input by three: {}", e))?;
-
-    if i % 3 != 0 {
-        Err("Number is not divisible by 3")?
-    }
-
-    Ok(())
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unwrap_or_else_default.txt b/src/tools/clippy/src/docs/unwrap_or_else_default.txt
deleted file mode 100644
index 34b4cf08858..00000000000
--- a/src/tools/clippy/src/docs/unwrap_or_else_default.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for usages of `_.unwrap_or_else(Default::default)` on `Option` and
-`Result` values.
-
-### Why is this bad?
-Readability, these can be written as `_.unwrap_or_default`, which is
-simpler and more concise.
-
-### Examples
-```
-x.unwrap_or_else(Default::default);
-x.unwrap_or_else(u32::default);
-```
-
-Use instead:
-```
-x.unwrap_or_default();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unwrap_used.txt b/src/tools/clippy/src/docs/unwrap_used.txt
deleted file mode 100644
index 9b4713df515..00000000000
--- a/src/tools/clippy/src/docs/unwrap_used.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-### What it does
-Checks for `.unwrap()` or `.unwrap_err()` calls on `Result`s and `.unwrap()` call on `Option`s.
-
-### Why is this bad?
-It is better to handle the `None` or `Err` case,
-or at least call `.expect(_)` with a more helpful message. Still, for a lot of
-quick-and-dirty code, `unwrap` is a good choice, which is why this lint is
-`Allow` by default.
-
-`result.unwrap()` will let the thread panic on `Err` values.
-Normally, you want to implement more sophisticated error handling,
-and propagate errors upwards with `?` operator.
-
-Even if you want to panic on errors, not all `Error`s implement good
-messages on display. Therefore, it may be beneficial to look at the places
-where they may get displayed. Activate this lint to do just that.
-
-### Examples
-```
-option.unwrap();
-result.unwrap();
-```
-
-Use instead:
-```
-option.expect("more helpful message");
-result.expect("more helpful message");
-```
-
-If [expect_used](#expect_used) is enabled, instead:
-```
-option?;
-
-// or
-
-result?;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/upper_case_acronyms.txt b/src/tools/clippy/src/docs/upper_case_acronyms.txt
deleted file mode 100644
index a1e39c7e10c..00000000000
--- a/src/tools/clippy/src/docs/upper_case_acronyms.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Checks for fully capitalized names and optionally names containing a capitalized acronym.
-
-### Why is this bad?
-In CamelCase, acronyms count as one word.
-See [naming conventions](https://rust-lang.github.io/api-guidelines/naming.html#casing-conforms-to-rfc-430-c-case)
-for more.
-
-By default, the lint only triggers on fully-capitalized names.
-You can use the `upper-case-acronyms-aggressive: true` config option to enable linting
-on all camel case names
-
-### Known problems
-When two acronyms are contiguous, the lint can't tell where
-the first acronym ends and the second starts, so it suggests to lowercase all of
-the letters in the second acronym.
-
-### Example
-```
-struct HTTPResponse;
-```
-Use instead:
-```
-struct HttpResponse;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/use_debug.txt b/src/tools/clippy/src/docs/use_debug.txt
deleted file mode 100644
index 94d4a6fd29a..00000000000
--- a/src/tools/clippy/src/docs/use_debug.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for use of `Debug` formatting. The purpose of this
-lint is to catch debugging remnants.
-
-### Why is this bad?
-The purpose of the `Debug` trait is to facilitate
-debugging Rust code. It should not be used in user-facing output.
-
-### Example
-```
-println!("{:?}", foo);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/use_self.txt b/src/tools/clippy/src/docs/use_self.txt
deleted file mode 100644
index bd37ed1e002..00000000000
--- a/src/tools/clippy/src/docs/use_self.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-### What it does
-Checks for unnecessary repetition of structure name when a
-replacement with `Self` is applicable.
-
-### Why is this bad?
-Unnecessary repetition. Mixed use of `Self` and struct
-name
-feels inconsistent.
-
-### Known problems
-- Unaddressed false negative in fn bodies of trait implementations
-- False positive with associated types in traits (#4140)
-
-### Example
-```
-struct Foo;
-impl Foo {
-    fn new() -> Foo {
-        Foo {}
-    }
-}
-```
-could be
-```
-struct Foo;
-impl Foo {
-    fn new() -> Self {
-        Self {}
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/used_underscore_binding.txt b/src/tools/clippy/src/docs/used_underscore_binding.txt
deleted file mode 100644
index ed67c41eb0d..00000000000
--- a/src/tools/clippy/src/docs/used_underscore_binding.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-### What it does
-Checks for the use of bindings with a single leading
-underscore.
-
-### Why is this bad?
-A single leading underscore is usually used to indicate
-that a binding will not be used. Using such a binding breaks this
-expectation.
-
-### Known problems
-The lint does not work properly with desugaring and
-macro, it has been allowed in the mean time.
-
-### Example
-```
-let _x = 0;
-let y = _x + 1; // Here we are using `_x`, even though it has a leading
-                // underscore. We should rename `_x` to `x`
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/useless_asref.txt b/src/tools/clippy/src/docs/useless_asref.txt
deleted file mode 100644
index f777cd3775e..00000000000
--- a/src/tools/clippy/src/docs/useless_asref.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for usage of `.as_ref()` or `.as_mut()` where the
-types before and after the call are the same.
-
-### Why is this bad?
-The call is unnecessary.
-
-### Example
-```
-let x: &[i32] = &[1, 2, 3, 4, 5];
-do_stuff(x.as_ref());
-```
-The correct use would be:
-```
-let x: &[i32] = &[1, 2, 3, 4, 5];
-do_stuff(x);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/useless_attribute.txt b/src/tools/clippy/src/docs/useless_attribute.txt
deleted file mode 100644
index e02d4c90789..00000000000
--- a/src/tools/clippy/src/docs/useless_attribute.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-### What it does
-Checks for `extern crate` and `use` items annotated with
-lint attributes.
-
-This lint permits lint attributes for lints emitted on the items themself.
-For `use` items these lints are:
-* deprecated
-* unreachable_pub
-* unused_imports
-* clippy::enum_glob_use
-* clippy::macro_use_imports
-* clippy::wildcard_imports
-
-For `extern crate` items these lints are:
-* `unused_imports` on items with `#[macro_use]`
-
-### Why is this bad?
-Lint attributes have no effect on crate imports. Most
-likely a `!` was forgotten.
-
-### Example
-```
-#[deny(dead_code)]
-extern crate foo;
-#[forbid(dead_code)]
-use foo::bar;
-```
-
-Use instead:
-```
-#[allow(unused_imports)]
-use foo::baz;
-#[allow(unused_imports)]
-#[macro_use]
-extern crate baz;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/useless_conversion.txt b/src/tools/clippy/src/docs/useless_conversion.txt
deleted file mode 100644
index 06000a7ad98..00000000000
--- a/src/tools/clippy/src/docs/useless_conversion.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for `Into`, `TryInto`, `From`, `TryFrom`, or `IntoIter` calls
-which uselessly convert to the same type.
-
-### Why is this bad?
-Redundant code.
-
-### Example
-```
-// format!() returns a `String`
-let s: String = format!("hello").into();
-```
-
-Use instead:
-```
-let s: String = format!("hello");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/useless_format.txt b/src/tools/clippy/src/docs/useless_format.txt
deleted file mode 100644
index eb4819da1e9..00000000000
--- a/src/tools/clippy/src/docs/useless_format.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for the use of `format!("string literal with no
-argument")` and `format!("{}", foo)` where `foo` is a string.
-
-### Why is this bad?
-There is no point of doing that. `format!("foo")` can
-be replaced by `"foo".to_owned()` if you really need a `String`. The even
-worse `&format!("foo")` is often encountered in the wild. `format!("{}",
-foo)` can be replaced by `foo.clone()` if `foo: String` or `foo.to_owned()`
-if `foo: &str`.
-
-### Examples
-```
-let foo = "foo";
-format!("{}", foo);
-```
-
-Use instead:
-```
-let foo = "foo";
-foo.to_owned();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/useless_let_if_seq.txt b/src/tools/clippy/src/docs/useless_let_if_seq.txt
deleted file mode 100644
index c6dcd57eb2e..00000000000
--- a/src/tools/clippy/src/docs/useless_let_if_seq.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-### What it does
-Checks for variable declarations immediately followed by a
-conditional affectation.
-
-### Why is this bad?
-This is not idiomatic Rust.
-
-### Example
-```
-let foo;
-
-if bar() {
-    foo = 42;
-} else {
-    foo = 0;
-}
-
-let mut baz = None;
-
-if bar() {
-    baz = Some(42);
-}
-```
-
-should be written
-
-```
-let foo = if bar() {
-    42
-} else {
-    0
-};
-
-let baz = if bar() {
-    Some(42)
-} else {
-    None
-};
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/useless_transmute.txt b/src/tools/clippy/src/docs/useless_transmute.txt
deleted file mode 100644
index 1d3a1758814..00000000000
--- a/src/tools/clippy/src/docs/useless_transmute.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-### What it does
-Checks for transmutes to the original type of the object
-and transmutes that could be a cast.
-
-### Why is this bad?
-Readability. The code tricks people into thinking that
-something complex is going on.
-
-### Example
-```
-core::intrinsics::transmute(t); // where the result type is the same as `t`'s
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/useless_vec.txt b/src/tools/clippy/src/docs/useless_vec.txt
deleted file mode 100644
index ee5afc99e4b..00000000000
--- a/src/tools/clippy/src/docs/useless_vec.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-Checks for usage of `&vec![..]` when using `&[..]` would
-be possible.
-
-### Why is this bad?
-This is less efficient.
-
-### Example
-```
-fn foo(_x: &[u8]) {}
-
-foo(&vec![1, 2]);
-```
-
-Use instead:
-```
-foo(&[1, 2]);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/vec_box.txt b/src/tools/clippy/src/docs/vec_box.txt
deleted file mode 100644
index 701b1c9ce9b..00000000000
--- a/src/tools/clippy/src/docs/vec_box.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-### What it does
-Checks for use of `Vec<Box<T>>` where T: Sized anywhere in the code.
-Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information.
-
-### Why is this bad?
-`Vec` already keeps its contents in a separate area on
-the heap. So if you `Box` its contents, you just add another level of indirection.
-
-### Known problems
-Vec<Box<T: Sized>> makes sense if T is a large type (see [#3530](https://github.com/rust-lang/rust-clippy/issues/3530),
-1st comment).
-
-### Example
-```
-struct X {
-    values: Vec<Box<i32>>,
-}
-```
-
-Better:
-
-```
-struct X {
-    values: Vec<i32>,
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/vec_init_then_push.txt b/src/tools/clippy/src/docs/vec_init_then_push.txt
deleted file mode 100644
index 445f2874796..00000000000
--- a/src/tools/clippy/src/docs/vec_init_then_push.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-### What it does
-Checks for calls to `push` immediately after creating a new `Vec`.
-
-If the `Vec` is created using `with_capacity` this will only lint if the capacity is a
-constant and the number of pushes is greater than or equal to the initial capacity.
-
-If the `Vec` is extended after the initial sequence of pushes and it was default initialized
-then this will only lint after there were at least four pushes. This number may change in
-the future.
-
-### Why is this bad?
-The `vec![]` macro is both more performant and easier to read than
-multiple `push` calls.
-
-### Example
-```
-let mut v = Vec::new();
-v.push(0);
-```
-Use instead:
-```
-let v = vec![0];
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/vec_resize_to_zero.txt b/src/tools/clippy/src/docs/vec_resize_to_zero.txt
deleted file mode 100644
index 0b92686772b..00000000000
--- a/src/tools/clippy/src/docs/vec_resize_to_zero.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Finds occurrences of `Vec::resize(0, an_int)`
-
-### Why is this bad?
-This is probably an argument inversion mistake.
-
-### Example
-```
-vec!(1, 2, 3, 4, 5).resize(0, 5)
-```
-
-Use instead:
-```
-vec!(1, 2, 3, 4, 5).clear()
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/verbose_bit_mask.txt b/src/tools/clippy/src/docs/verbose_bit_mask.txt
deleted file mode 100644
index 87a84702925..00000000000
--- a/src/tools/clippy/src/docs/verbose_bit_mask.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for bit masks that can be replaced by a call
-to `trailing_zeros`
-
-### Why is this bad?
-`x.trailing_zeros() > 4` is much clearer than `x & 15
-== 0`
-
-### Known problems
-llvm generates better code for `x & 15 == 0` on x86
-
-### Example
-```
-if x & 0b1111 == 0 { }
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/verbose_file_reads.txt b/src/tools/clippy/src/docs/verbose_file_reads.txt
deleted file mode 100644
index 9703df423a5..00000000000
--- a/src/tools/clippy/src/docs/verbose_file_reads.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for use of File::read_to_end and File::read_to_string.
-
-### Why is this bad?
-`fs::{read, read_to_string}` provide the same functionality when `buf` is empty with fewer imports and no intermediate values.
-See also: [fs::read docs](https://doc.rust-lang.org/std/fs/fn.read.html), [fs::read_to_string docs](https://doc.rust-lang.org/std/fs/fn.read_to_string.html)
-
-### Example
-```
-let mut f = File::open("foo.txt").unwrap();
-let mut bytes = Vec::new();
-f.read_to_end(&mut bytes).unwrap();
-```
-Can be written more concisely as
-```
-let mut bytes = fs::read("foo.txt").unwrap();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/vtable_address_comparisons.txt b/src/tools/clippy/src/docs/vtable_address_comparisons.txt
deleted file mode 100644
index 4a34e4ba78e..00000000000
--- a/src/tools/clippy/src/docs/vtable_address_comparisons.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-Checks for comparisons with an address of a trait vtable.
-
-### Why is this bad?
-Comparing trait objects pointers compares an vtable addresses which
-are not guaranteed to be unique and could vary between different code generation units.
-Furthermore vtables for different types could have the same address after being merged
-together.
-
-### Example
-```
-let a: Rc<dyn Trait> = ...
-let b: Rc<dyn Trait> = ...
-if Rc::ptr_eq(&a, &b) {
-    ...
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/while_immutable_condition.txt b/src/tools/clippy/src/docs/while_immutable_condition.txt
deleted file mode 100644
index 71800701f48..00000000000
--- a/src/tools/clippy/src/docs/while_immutable_condition.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks whether variables used within while loop condition
-can be (and are) mutated in the body.
-
-### Why is this bad?
-If the condition is unchanged, entering the body of the loop
-will lead to an infinite loop.
-
-### Known problems
-If the `while`-loop is in a closure, the check for mutation of the
-condition variables in the body can cause false negatives. For example when only `Upvar` `a` is
-in the condition and only `Upvar` `b` gets mutated in the body, the lint will not trigger.
-
-### Example
-```
-let i = 0;
-while i > 10 {
-    println!("let me loop forever!");
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/while_let_loop.txt b/src/tools/clippy/src/docs/while_let_loop.txt
deleted file mode 100644
index ab7bf60975e..00000000000
--- a/src/tools/clippy/src/docs/while_let_loop.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Detects `loop + match` combinations that are easier
-written as a `while let` loop.
-
-### Why is this bad?
-The `while let` loop is usually shorter and more
-readable.
-
-### Known problems
-Sometimes the wrong binding is displayed ([#383](https://github.com/rust-lang/rust-clippy/issues/383)).
-
-### Example
-```
-loop {
-    let x = match y {
-        Some(x) => x,
-        None => break,
-    };
-    // .. do something with x
-}
-// is easier written as
-while let Some(x) = y {
-    // .. do something with x
-};
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/while_let_on_iterator.txt b/src/tools/clippy/src/docs/while_let_on_iterator.txt
deleted file mode 100644
index af053c54119..00000000000
--- a/src/tools/clippy/src/docs/while_let_on_iterator.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-### What it does
-Checks for `while let` expressions on iterators.
-
-### Why is this bad?
-Readability. A simple `for` loop is shorter and conveys
-the intent better.
-
-### Example
-```
-while let Some(val) = iter.next() {
-    ..
-}
-```
-
-Use instead:
-```
-for val in &mut iter {
-    ..
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/wildcard_dependencies.txt b/src/tools/clippy/src/docs/wildcard_dependencies.txt
deleted file mode 100644
index 2affaf9740d..00000000000
--- a/src/tools/clippy/src/docs/wildcard_dependencies.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-### What it does
-Checks for wildcard dependencies in the `Cargo.toml`.
-
-### Why is this bad?
-[As the edition guide says](https://rust-lang-nursery.github.io/edition-guide/rust-2018/cargo-and-crates-io/crates-io-disallows-wildcard-dependencies.html),
-it is highly unlikely that you work with any possible version of your dependency,
-and wildcard dependencies would cause unnecessary breakage in the ecosystem.
-
-### Example
-```
-[dependencies]
-regex = "*"
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/wildcard_enum_match_arm.txt b/src/tools/clippy/src/docs/wildcard_enum_match_arm.txt
deleted file mode 100644
index 09807c01c65..00000000000
--- a/src/tools/clippy/src/docs/wildcard_enum_match_arm.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-### What it does
-Checks for wildcard enum matches using `_`.
-
-### Why is this bad?
-New enum variants added by library updates can be missed.
-
-### Known problems
-Suggested replacements may be incorrect if guards exhaustively cover some
-variants, and also may not use correct path to enum if it's not present in the current scope.
-
-### Example
-```
-match x {
-    Foo::A(_) => {},
-    _ => {},
-}
-```
-
-Use instead:
-```
-match x {
-    Foo::A(_) => {},
-    Foo::B(_) => {},
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/wildcard_imports.txt b/src/tools/clippy/src/docs/wildcard_imports.txt
deleted file mode 100644
index bd56aa5b082..00000000000
--- a/src/tools/clippy/src/docs/wildcard_imports.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-### What it does
-Checks for wildcard imports `use _::*`.
-
-### Why is this bad?
-wildcard imports can pollute the namespace. This is especially bad if
-you try to import something through a wildcard, that already has been imported by name from
-a different source:
-
-```
-use crate1::foo; // Imports a function named foo
-use crate2::*; // Has a function named foo
-
-foo(); // Calls crate1::foo
-```
-
-This can lead to confusing error messages at best and to unexpected behavior at worst.
-
-### Exceptions
-Wildcard imports are allowed from modules named `prelude`. Many crates (including the standard library)
-provide modules named "prelude" specifically designed for wildcard import.
-
-`use super::*` is allowed in test modules. This is defined as any module with "test" in the name.
-
-These exceptions can be disabled using the `warn-on-all-wildcard-imports` configuration flag.
-
-### Known problems
-If macros are imported through the wildcard, this macro is not included
-by the suggestion and has to be added by hand.
-
-Applying the suggestion when explicit imports of the things imported with a glob import
-exist, may result in `unused_imports` warnings.
-
-### Example
-```
-use crate1::*;
-
-foo();
-```
-
-Use instead:
-```
-use crate1::foo;
-
-foo();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/wildcard_in_or_patterns.txt b/src/tools/clippy/src/docs/wildcard_in_or_patterns.txt
deleted file mode 100644
index 70468ca41e0..00000000000
--- a/src/tools/clippy/src/docs/wildcard_in_or_patterns.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-### What it does
-Checks for wildcard pattern used with others patterns in same match arm.
-
-### Why is this bad?
-Wildcard pattern already covers any other pattern as it will match anyway.
-It makes the code less readable, especially to spot wildcard pattern use in match arm.
-
-### Example
-```
-match s {
-    "a" => {},
-    "bar" | _ => {},
-}
-```
-
-Use instead:
-```
-match s {
-    "a" => {},
-    _ => {},
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/write_literal.txt b/src/tools/clippy/src/docs/write_literal.txt
deleted file mode 100644
index a7a884d0871..00000000000
--- a/src/tools/clippy/src/docs/write_literal.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-### What it does
-This lint warns about the use of literals as `write!`/`writeln!` args.
-
-### Why is this bad?
-Using literals as `writeln!` args is inefficient
-(c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
-(i.e., just put the literal in the format string)
-
-### Example
-```
-writeln!(buf, "{}", "foo");
-```
-
-Use instead:
-```
-writeln!(buf, "foo");
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/write_with_newline.txt b/src/tools/clippy/src/docs/write_with_newline.txt
deleted file mode 100644
index 22845fd6515..00000000000
--- a/src/tools/clippy/src/docs/write_with_newline.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-### What it does
-This lint warns when you use `write!()` with a format
-string that
-ends in a newline.
-
-### Why is this bad?
-You should use `writeln!()` instead, which appends the
-newline.
-
-### Example
-```
-write!(buf, "Hello {}!\n", name);
-```
-
-Use instead:
-```
-writeln!(buf, "Hello {}!", name);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/writeln_empty_string.txt b/src/tools/clippy/src/docs/writeln_empty_string.txt
deleted file mode 100644
index 3b3aeb79a48..00000000000
--- a/src/tools/clippy/src/docs/writeln_empty_string.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-This lint warns when you use `writeln!(buf, "")` to
-print a newline.
-
-### Why is this bad?
-You should use `writeln!(buf)`, which is simpler.
-
-### Example
-```
-writeln!(buf, "");
-```
-
-Use instead:
-```
-writeln!(buf);
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/wrong_self_convention.txt b/src/tools/clippy/src/docs/wrong_self_convention.txt
deleted file mode 100644
index d6b69ab87f8..00000000000
--- a/src/tools/clippy/src/docs/wrong_self_convention.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-### What it does
-Checks for methods with certain name prefixes and which
-doesn't match how self is taken. The actual rules are:
-
-|Prefix |Postfix     |`self` taken                   | `self` type  |
-|-------|------------|-------------------------------|--------------|
-|`as_`  | none       |`&self` or `&mut self`         | any          |
-|`from_`| none       | none                          | any          |
-|`into_`| none       |`self`                         | any          |
-|`is_`  | none       |`&mut self` or `&self` or none | any          |
-|`to_`  | `_mut`     |`&mut self`                    | any          |
-|`to_`  | not `_mut` |`self`                         | `Copy`       |
-|`to_`  | not `_mut` |`&self`                        | not `Copy`   |
-
-Note: Clippy doesn't trigger methods with `to_` prefix in:
-- Traits definition.
-Clippy can not tell if a type that implements a trait is `Copy` or not.
-- Traits implementation, when `&self` is taken.
-The method signature is controlled by the trait and often `&self` is required for all types that implement the trait
-(see e.g. the `std::string::ToString` trait).
-
-Clippy allows `Pin<&Self>` and `Pin<&mut Self>` if `&self` and `&mut self` is required.
-
-Please find more info here:
-https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv
-
-### Why is this bad?
-Consistency breeds readability. If you follow the
-conventions, your users won't be surprised that they, e.g., need to supply a
-mutable reference to a `as_..` function.
-
-### Example
-```
-impl X {
-    fn as_str(self) -> &'static str {
-        // ..
-    }
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/wrong_transmute.txt b/src/tools/clippy/src/docs/wrong_transmute.txt
deleted file mode 100644
index 9fc71e0e382..00000000000
--- a/src/tools/clippy/src/docs/wrong_transmute.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for transmutes that can't ever be correct on any
-architecture.
-
-### Why is this bad?
-It's basically guaranteed to be undefined behavior.
-
-### Known problems
-When accessing C, users might want to store pointer
-sized objects in `extradata` arguments to save an allocation.
-
-### Example
-```
-let ptr: *const T = core::intrinsics::transmute('x')
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/zero_divided_by_zero.txt b/src/tools/clippy/src/docs/zero_divided_by_zero.txt
deleted file mode 100644
index 394de20c0c0..00000000000
--- a/src/tools/clippy/src/docs/zero_divided_by_zero.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-Checks for `0.0 / 0.0`.
-
-### Why is this bad?
-It's less readable than `f32::NAN` or `f64::NAN`.
-
-### Example
-```
-let nan = 0.0f32 / 0.0;
-```
-
-Use instead:
-```
-let nan = f32::NAN;
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/zero_prefixed_literal.txt b/src/tools/clippy/src/docs/zero_prefixed_literal.txt
deleted file mode 100644
index 5c558872536..00000000000
--- a/src/tools/clippy/src/docs/zero_prefixed_literal.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-### What it does
-Warns if an integral constant literal starts with `0`.
-
-### Why is this bad?
-In some languages (including the infamous C language
-and most of its
-family), this marks an octal constant. In Rust however, this is a decimal
-constant. This could
-be confusing for both the writer and a reader of the constant.
-
-### Example
-
-In Rust:
-```
-fn main() {
-    let a = 0123;
-    println!("{}", a);
-}
-```
-
-prints `123`, while in C:
-
-```
-#include <stdio.h>
-
-int main() {
-    int a = 0123;
-    printf("%d\n", a);
-}
-```
-
-prints `83` (as `83 == 0o123` while `123 == 0o173`).
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/zero_ptr.txt b/src/tools/clippy/src/docs/zero_ptr.txt
deleted file mode 100644
index e768a023660..00000000000
--- a/src/tools/clippy/src/docs/zero_ptr.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-### What it does
-Catch casts from `0` to some pointer type
-
-### Why is this bad?
-This generally means `null` and is better expressed as
-{`std`, `core`}`::ptr::`{`null`, `null_mut`}.
-
-### Example
-```
-let a = 0 as *const u32;
-```
-
-Use instead:
-```
-let a = std::ptr::null::<u32>();
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/zero_sized_map_values.txt b/src/tools/clippy/src/docs/zero_sized_map_values.txt
deleted file mode 100644
index 0502bdbf395..00000000000
--- a/src/tools/clippy/src/docs/zero_sized_map_values.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-### What it does
-Checks for maps with zero-sized value types anywhere in the code.
-
-### Why is this bad?
-Since there is only a single value for a zero-sized type, a map
-containing zero sized values is effectively a set. Using a set in that case improves
-readability and communicates intent more clearly.
-
-### Known problems
-* A zero-sized type cannot be recovered later if it contains private fields.
-* This lints the signature of public items
-
-### Example
-```
-fn unique_words(text: &str) -> HashMap<&str, ()> {
-    todo!();
-}
-```
-Use instead:
-```
-fn unique_words(text: &str) -> HashSet<&str> {
-    todo!();
-}
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/docs/zst_offset.txt b/src/tools/clippy/src/docs/zst_offset.txt
deleted file mode 100644
index 5810455ee95..00000000000
--- a/src/tools/clippy/src/docs/zst_offset.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-### What it does
-Checks for `offset(_)`, `wrapping_`{`add`, `sub`}, etc. on raw pointers to
-zero-sized types
-
-### Why is this bad?
-This is a no-op, and likely unintended
-
-### Example
-```
-unsafe { (&() as *const ()).offset(1) };
-```
\ No newline at end of file
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index f24d3507823..ad6132a49ba 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -1,4 +1,5 @@
 #![feature(rustc_private)]
+#![feature(let_chains)]
 #![feature(once_cell)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 // warn on lints, that are included in `rust-lang/rust`s bootstrap
@@ -71,6 +72,33 @@ fn track_clippy_args(parse_sess: &mut ParseSess, args_env_var: &Option<String>)
     ));
 }
 
+/// Track files that may be accessed at runtime in `file_depinfo` so that cargo will re-run clippy
+/// when any of them are modified
+fn track_files(parse_sess: &mut ParseSess, conf_path_string: Option<String>) {
+    let file_depinfo = parse_sess.file_depinfo.get_mut();
+
+    // Used by `clippy::cargo` lints and to determine the MSRV. `cargo clippy` executes `clippy-driver`
+    // with the current directory set to `CARGO_MANIFEST_DIR` so a relative path is fine
+    if Path::new("Cargo.toml").exists() {
+        file_depinfo.insert(Symbol::intern("Cargo.toml"));
+    }
+
+    // `clippy.toml`
+    if let Some(path) = conf_path_string {
+        file_depinfo.insert(Symbol::intern(&path));
+    }
+
+    // During development track the `clippy-driver` executable so that cargo will re-run clippy whenever
+    // it is rebuilt
+    if cfg!(debug_assertions) {
+        if let Ok(current_exe) = env::current_exe()
+            && let Some(current_exe) = current_exe.to_str()
+        {
+            file_depinfo.insert(Symbol::intern(current_exe));
+        }
+    }
+}
+
 struct DefaultCallbacks;
 impl rustc_driver::Callbacks for DefaultCallbacks {}
 
@@ -97,10 +125,18 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
     // JUSTIFICATION: necessary in clippy driver to set `mir_opt_level`
     #[allow(rustc::bad_opt_access)]
     fn config(&mut self, config: &mut interface::Config) {
+        let conf_path = clippy_lints::lookup_conf_file();
+        let conf_path_string = if let Ok(Some(path)) = &conf_path {
+            path.to_str().map(String::from)
+        } else {
+            None
+        };
+
         let previous = config.register_lints.take();
         let clippy_args_var = self.clippy_args_var.take();
         config.parse_sess_created = Some(Box::new(move |parse_sess| {
             track_clippy_args(parse_sess, &clippy_args_var);
+            track_files(parse_sess, conf_path_string);
         }));
         config.register_lints = Some(Box::new(move |sess, lint_store| {
             // technically we're ~guaranteed that this is none but might as well call anything that
@@ -109,7 +145,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
                 (previous)(sess, lint_store);
             }
 
-            let conf = clippy_lints::read_conf(sess);
+            let conf = clippy_lints::read_conf(sess, &conf_path);
             clippy_lints::register_plugins(lint_store, sess, &conf);
             clippy_lints::register_pre_expansion_lints(lint_store, sess, &conf);
             clippy_lints::register_renamed(lint_store);
@@ -217,6 +253,13 @@ pub fn main() {
     exit(rustc_driver::catch_with_exit_code(move || {
         let mut orig_args: Vec<String> = env::args().collect();
 
+        let sys_root_env = std::env::var("SYSROOT").ok();
+        let pass_sysroot_env_if_given = |args: &mut Vec<String>, sys_root_env| {
+            if let Some(sys_root) = sys_root_env {
+                args.extend(vec!["--sysroot".into(), sys_root]);
+            };
+        };
+
         // make "clippy-driver --rustc" work like a subcommand that passes further args to "rustc"
         // for example `clippy-driver --rustc --version` will print the rustc version that clippy-driver
         // uses
@@ -224,7 +267,10 @@ pub fn main() {
             orig_args.remove(pos);
             orig_args[0] = "rustc".to_string();
 
-            return rustc_driver::RunCompiler::new(&orig_args, &mut DefaultCallbacks).run();
+            let mut args: Vec<String> = orig_args.clone();
+            pass_sysroot_env_if_given(&mut args, sys_root_env);
+
+            return rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run();
         }
 
         if orig_args.iter().any(|a| a == "--version" || a == "-V") {
@@ -247,6 +293,9 @@ pub fn main() {
             exit(0);
         }
 
+        let mut args: Vec<String> = orig_args.clone();
+        pass_sysroot_env_if_given(&mut args, sys_root_env);
+
         let mut no_deps = false;
         let clippy_args_var = env::var("CLIPPY_ARGS").ok();
         let clippy_args = clippy_args_var
@@ -275,11 +324,10 @@ pub fn main() {
 
         let clippy_enabled = !cap_lints_allow && (!no_deps || in_primary_package);
         if clippy_enabled {
-            let mut args: Vec<String> = orig_args.clone();
             args.extend(clippy_args);
             rustc_driver::RunCompiler::new(&args, &mut ClippyCallbacks { clippy_args_var }).run()
         } else {
-            rustc_driver::RunCompiler::new(&orig_args, &mut RustcCallbacks { clippy_args_var }).run()
+            rustc_driver::RunCompiler::new(&args, &mut RustcCallbacks { clippy_args_var }).run()
         }
     }))
 }
diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs
index fce3cdfc462..d418d2daa31 100644
--- a/src/tools/clippy/src/main.rs
+++ b/src/tools/clippy/src/main.rs
@@ -7,8 +7,6 @@ use std::env;
 use std::path::PathBuf;
 use std::process::{self, Command};
 
-mod docs;
-
 const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.
 
 Usage:
@@ -60,7 +58,7 @@ pub fn main() {
     if let Some(pos) = env::args().position(|a| a == "--explain") {
         if let Some(mut lint) = env::args().nth(pos + 1) {
             lint.make_ascii_lowercase();
-            docs::explain(&lint.strip_prefix("clippy::").unwrap_or(&lint).replace('-', "_"));
+            clippy_lints::explain(&lint.strip_prefix("clippy::").unwrap_or(&lint).replace('-', "_"));
         } else {
             show_help();
         }
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr
index 9a7d802dc6d..163f8bb35e7 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr
@@ -12,5 +12,11 @@ note: the lint level is defined here
 LL | #![deny(clippy::use_self)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: unnecessary structure name repetition
+  --> $DIR/main.rs:7:9
+   |
+LL |         Foo
+   |         ^^^ help: use the applicable keyword: `Self`
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr
index a280e1bacdf..259d39b1252 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr
@@ -10,5 +10,11 @@ note: the lint level is defined here
 LL | #![deny(clippy::use_self)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: unnecessary structure name repetition
+  --> $DIR/main.rs:7:9
+   |
+LL |         Foo
+   |         ^^^ help: use the applicable keyword: `Self`
+
+error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr
index a280e1bacdf..259d39b1252 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr
@@ -10,5 +10,11 @@ note: the lint level is defined here
 LL | #![deny(clippy::use_self)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: unnecessary structure name repetition
+  --> $DIR/main.rs:7:9
+   |
+LL |         Foo
+   |         ^^^ help: use the applicable keyword: `Self`
+
+error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr
index a280e1bacdf..259d39b1252 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr
@@ -10,5 +10,11 @@ note: the lint level is defined here
 LL | #![deny(clippy::use_self)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: unnecessary structure name repetition
+  --> $DIR/main.rs:7:9
+   |
+LL |         Foo
+   |         ^^^ help: use the applicable keyword: `Self`
+
+error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr
index 88f6e00922b..97e6c3d5a55 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr
@@ -10,5 +10,11 @@ note: the lint level is defined here
 LL | #![deny(clippy::use_self)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: unnecessary structure name repetition
+  --> $DIR/main.rs:12:9
+   |
+LL |         Foo
+   |         ^^^ help: use the applicable keyword: `Self`
+
+error: aborting due to 2 previous errors
 
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 5057a018300..4be04f77f5b 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
@@ -2,6 +2,7 @@
 // normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo"
 // normalize-stderr-test: "internal_lints.rs:\d*:\d*" -> "internal_lints.rs"
 // normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints"
+// normalize-stderr-test: "'rustc'" -> "'<unnamed>'"
 
 #![deny(clippy::internal)]
 #![allow(clippy::missing_clippy_version_attribute)]
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 07c5941013c..2ba5890660f 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
@@ -1,4 +1,4 @@
-thread 'rustc' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs:28:9
+thread '<unnamed>' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs:28:9
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
 error: internal compiler error: unexpected panic
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
index 2a240cc249b..8bfc060e991 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
@@ -1,3 +1,12 @@
+error: hardcoded path to a language item
+  --> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
+   |
+LL |     const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"];
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: convert all references to use `LangItem::DerefMut`
+   = note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
+
 error: hardcoded path to a diagnostic item
   --> $DIR/unnecessary_def_path_hardcoded_path.rs:10:36
    |
@@ -5,7 +14,6 @@ LL |     const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: convert all references to use `sym::Deref`
-   = note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
 
 error: hardcoded path to a diagnostic item
   --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
@@ -15,13 +23,5 @@ LL |     const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref",
    |
    = help: convert all references to use `sym::deref_method`
 
-error: hardcoded path to a language item
-  --> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
-   |
-LL |     const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"];
-   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: convert all references to use `LangItem::DerefMut`
-
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs b/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs
index 1aed09b7c7b..e8a023ab176 100644
--- a/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs
+++ b/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs
@@ -1,6 +1,6 @@
 #![warn(clippy::arithmetic_side_effects)]
 
-use core::ops::Add;
+use core::ops::{Add, Neg};
 
 #[derive(Clone, Copy)]
 struct Point {
@@ -16,9 +16,18 @@ impl Add for Point {
     }
 }
 
+impl Neg for Point {
+    type Output = Self;
+
+    fn neg(self) -> Self::Output {
+        todo!()
+    }
+}
+
 fn main() {
     let _ = Point { x: 1, y: 0 } + Point { x: 2, y: 3 };
 
     let point: Point = Point { x: 1, y: 0 };
     let _ = point + point;
+    let _ = -point;
 }
diff --git a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
index 4c75998437f..825aa1487e7 100644
--- a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
+++ b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
@@ -4,7 +4,7 @@ error: `std::string::String` may not be held across an `await` point per `clippy
 LL |     let _x = String::from("hello");
    |         ^^
    |
-   = note: strings are bad
+   = note: strings are bad (from clippy.toml)
    = note: `-D clippy::await-holding-invalid-type` implied by `-D warnings`
 
 error: `std::net::Ipv4Addr` may not be held across an `await` point per `clippy.toml`
@@ -19,7 +19,7 @@ error: `std::string::String` may not be held across an `await` point per `clippy
 LL |         let _x = String::from("hi!");
    |             ^^
    |
-   = note: strings are bad
+   = note: strings are bad (from clippy.toml)
 
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
index 22dcd3ae9d6..bff97d97df7 100644
--- a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
+++ b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
@@ -16,14 +16,19 @@ fn main() {
     expect_result();
 }
 
-#[test]
-fn test_expect_option() {
-    let opt = Some(0);
-    let _ = opt.expect("");
-}
+#[cfg(test)]
+mod issue9612 {
+    // should not lint in `#[cfg(test)]` modules
+    #[test]
+    fn test_fn() {
+        let _a: u8 = 2.try_into().unwrap();
+        let _a: u8 = 3.try_into().expect("");
 
-#[test]
-fn test_expect_result() {
-    let res: Result<u8, ()> = Ok(0);
-    let _ = res.expect("");
+        util();
+    }
+
+    fn util() {
+        let _a: u8 = 4.try_into().unwrap();
+        let _a: u8 = 5.try_into().expect("");
+    }
 }
diff --git a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr
index 28a08599c67..1e9bb48c333 100644
--- a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr
+++ b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr
@@ -1,4 +1,4 @@
-error: used `expect()` on `an Option` value
+error: used `expect()` on an `Option` value
   --> $DIR/expect_used.rs:6:13
    |
 LL |     let _ = opt.expect("");
@@ -7,7 +7,7 @@ LL |     let _ = opt.expect("");
    = help: if this value is `None`, it will panic
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
-error: used `expect()` on `a Result` value
+error: used `expect()` on a `Result` value
   --> $DIR/expect_used.rs:11:13
    |
 LL |     let _ = res.expect("");
diff --git a/src/tools/clippy/tests/ui-toml/mut_key/clippy.toml b/src/tools/clippy/tests/ui-toml/mut_key/clippy.toml
new file mode 100644
index 00000000000..6d33e192ee8
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/mut_key/clippy.toml
@@ -0,0 +1 @@
+ignore-interior-mutability = ["mut_key::Counted"]
\ No newline at end of file
diff --git a/src/tools/clippy/tests/ui-toml/mut_key/mut_key.rs b/src/tools/clippy/tests/ui-toml/mut_key/mut_key.rs
new file mode 100644
index 00000000000..667c51cb4a3
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/mut_key/mut_key.rs
@@ -0,0 +1,53 @@
+// compile-flags: --crate-name mut_key
+
+#![warn(clippy::mutable_key_type)]
+
+use std::cmp::{Eq, PartialEq};
+use std::collections::{HashMap, HashSet};
+use std::hash::{Hash, Hasher};
+use std::ops::Deref;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+struct Counted<T> {
+    count: AtomicUsize,
+    val: T,
+}
+
+impl<T: Clone> Clone for Counted<T> {
+    fn clone(&self) -> Self {
+        Self {
+            count: AtomicUsize::new(0),
+            val: self.val.clone(),
+        }
+    }
+}
+
+impl<T: PartialEq> PartialEq for Counted<T> {
+    fn eq(&self, other: &Self) -> bool {
+        self.val == other.val
+    }
+}
+impl<T: PartialEq + Eq> Eq for Counted<T> {}
+
+impl<T: Hash> Hash for Counted<T> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.val.hash(state);
+    }
+}
+
+impl<T> Deref for Counted<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        self.count.fetch_add(1, Ordering::AcqRel);
+        &self.val
+    }
+}
+
+// This is not linted because `"mut_key::Counted"` is in
+// `arc_like_types` in `clippy.toml`
+fn should_not_take_this_arg(_v: HashSet<Counted<String>>) {}
+
+fn main() {
+    should_not_take_this_arg(HashSet::new());
+}
diff --git a/src/tools/clippy/tests/ui-toml/print_macro/clippy.toml b/src/tools/clippy/tests/ui-toml/print_macro/clippy.toml
new file mode 100644
index 00000000000..40b1dda5b2e
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/print_macro/clippy.toml
@@ -0,0 +1 @@
+allow-print-in-tests = true
diff --git a/src/tools/clippy/tests/ui-toml/print_macro/print_macro.rs b/src/tools/clippy/tests/ui-toml/print_macro/print_macro.rs
new file mode 100644
index 00000000000..5aefb6a6b4d
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/print_macro/print_macro.rs
@@ -0,0 +1,20 @@
+// compile-flags: --test
+#![warn(clippy::print_stdout)]
+#![warn(clippy::print_stderr)]
+
+fn foo(n: u32) {
+    print!("{n}");
+    eprint!("{n}");
+}
+
+#[test]
+pub fn foo1() {
+    print!("{}", 1);
+    eprint!("{}", 1);
+}
+
+#[cfg(test)]
+fn foo3() {
+    print!("{}", 1);
+    eprint!("{}", 1);
+}
diff --git a/src/tools/clippy/tests/ui-toml/print_macro/print_macro.stderr b/src/tools/clippy/tests/ui-toml/print_macro/print_macro.stderr
new file mode 100644
index 00000000000..d4b1ae84fd7
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/print_macro/print_macro.stderr
@@ -0,0 +1,18 @@
+error: use of `print!`
+  --> $DIR/print_macro.rs:6:5
+   |
+LL |     print!("{n}");
+   |     ^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::print-stdout` implied by `-D warnings`
+
+error: use of `eprint!`
+  --> $DIR/print_macro.rs:7:5
+   |
+LL |     eprint!("{n}");
+   |     ^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::print-stderr` implied by `-D warnings`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/clippy.toml b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/clippy.toml
index 28774db625b..41dbd506847 100644
--- a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/clippy.toml
+++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/clippy.toml
@@ -8,4 +8,10 @@ disallowed-methods = [
     { path = "regex::Regex::is_match", reason = "no matching allowed" },
     # can use an inline table but omit reason
     { path = "regex::Regex::new" },
+    # local paths
+    "conf_disallowed_methods::local_fn",
+    "conf_disallowed_methods::local_mod::f",
+    "conf_disallowed_methods::Struct::method",
+    "conf_disallowed_methods::Trait::provided_method",
+    "conf_disallowed_methods::Trait::implemented_method",
 ]
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
index b483f160028..2f3160c8338 100644
--- a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
+++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
@@ -1,3 +1,5 @@
+// compile-flags: --crate-name conf_disallowed_methods
+
 #![warn(clippy::disallowed_methods)]
 
 extern crate futures;
@@ -6,6 +8,27 @@ extern crate regex;
 use futures::stream::{empty, select_all};
 use regex::Regex;
 
+fn local_fn() {}
+
+struct Struct;
+
+impl Struct {
+    fn method(&self) {}
+}
+
+trait Trait {
+    fn provided_method(&self) {}
+    fn implemented_method(&self);
+}
+
+impl Trait for Struct {
+    fn implemented_method(&self) {}
+}
+
+mod local_mod {
+    pub fn f() {}
+}
+
 fn main() {
     let re = Regex::new(r"ab.*c").unwrap();
     re.is_match("abc");
@@ -26,4 +49,11 @@ fn main() {
 
     // resolve ambiguity between `futures::stream::select_all` the module and the function
     let same_name_as_module = select_all(vec![empty::<()>()]);
+
+    local_fn();
+    local_mod::f();
+    let s = Struct;
+    s.method();
+    s.provided_method();
+    s.implemented_method();
 }
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
index 6d78c32e127..148d1cae51f 100644
--- a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
+++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
@@ -1,5 +1,5 @@
 error: use of a disallowed method `regex::Regex::new`
-  --> $DIR/conf_disallowed_methods.rs:10:14
+  --> $DIR/conf_disallowed_methods.rs:33:14
    |
 LL |     let re = Regex::new(r"ab.*c").unwrap();
    |              ^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     let re = Regex::new(r"ab.*c").unwrap();
    = note: `-D clippy::disallowed-methods` implied by `-D warnings`
 
 error: use of a disallowed method `regex::Regex::is_match`
-  --> $DIR/conf_disallowed_methods.rs:11:5
+  --> $DIR/conf_disallowed_methods.rs:34:5
    |
 LL |     re.is_match("abc");
    |     ^^^^^^^^^^^^^^^^^^
@@ -15,46 +15,76 @@ LL |     re.is_match("abc");
    = note: no matching allowed (from clippy.toml)
 
 error: use of a disallowed method `std::iter::Iterator::sum`
-  --> $DIR/conf_disallowed_methods.rs:14:5
+  --> $DIR/conf_disallowed_methods.rs:37:5
    |
 LL |     a.iter().sum::<i32>();
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of a disallowed method `slice::sort_unstable`
-  --> $DIR/conf_disallowed_methods.rs:16:5
+  --> $DIR/conf_disallowed_methods.rs:39:5
    |
 LL |     a.sort_unstable();
    |     ^^^^^^^^^^^^^^^^^
 
 error: use of a disallowed method `f32::clamp`
-  --> $DIR/conf_disallowed_methods.rs:18:13
+  --> $DIR/conf_disallowed_methods.rs:41:13
    |
 LL |     let _ = 2.0f32.clamp(3.0f32, 4.0f32);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of a disallowed method `regex::Regex::new`
-  --> $DIR/conf_disallowed_methods.rs:21:61
+  --> $DIR/conf_disallowed_methods.rs:44:61
    |
 LL |     let indirect: fn(&str) -> Result<Regex, regex::Error> = Regex::new;
    |                                                             ^^^^^^^^^^
 
 error: use of a disallowed method `f32::clamp`
-  --> $DIR/conf_disallowed_methods.rs:24:28
+  --> $DIR/conf_disallowed_methods.rs:47:28
    |
 LL |     let in_call = Box::new(f32::clamp);
    |                            ^^^^^^^^^^
 
 error: use of a disallowed method `regex::Regex::new`
-  --> $DIR/conf_disallowed_methods.rs:25:53
+  --> $DIR/conf_disallowed_methods.rs:48:53
    |
 LL |     let in_method_call = ["^", "$"].into_iter().map(Regex::new);
    |                                                     ^^^^^^^^^^
 
 error: use of a disallowed method `futures::stream::select_all`
-  --> $DIR/conf_disallowed_methods.rs:28:31
+  --> $DIR/conf_disallowed_methods.rs:51:31
    |
 LL |     let same_name_as_module = select_all(vec![empty::<()>()]);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 9 previous errors
+error: use of a disallowed method `conf_disallowed_methods::local_fn`
+  --> $DIR/conf_disallowed_methods.rs:53:5
+   |
+LL |     local_fn();
+   |     ^^^^^^^^^^
+
+error: use of a disallowed method `conf_disallowed_methods::local_mod::f`
+  --> $DIR/conf_disallowed_methods.rs:54:5
+   |
+LL |     local_mod::f();
+   |     ^^^^^^^^^^^^^^
+
+error: use of a disallowed method `conf_disallowed_methods::Struct::method`
+  --> $DIR/conf_disallowed_methods.rs:56:5
+   |
+LL |     s.method();
+   |     ^^^^^^^^^^
+
+error: use of a disallowed method `conf_disallowed_methods::Trait::provided_method`
+  --> $DIR/conf_disallowed_methods.rs:57:5
+   |
+LL |     s.provided_method();
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: use of a disallowed method `conf_disallowed_methods::Trait::implemented_method`
+  --> $DIR/conf_disallowed_methods.rs:58:5
+   |
+LL |     s.implemented_method();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index 82ee8054132..f91d285c2e0 100644
--- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -1,6 +1,7 @@
 error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of
            allow-dbg-in-tests
            allow-expect-in-tests
+           allow-print-in-tests
            allow-unwrap-in-tests
            allowed-scripts
            arithmetic-side-effects-allowed
@@ -20,8 +21,10 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
            enforced-import-renames
            enum-variant-name-threshold
            enum-variant-size-threshold
+           ignore-interior-mutability
            large-error-threshold
            literal-representation-threshold
+           matches-for-let-else
            max-fn-params-bools
            max-include-file-size
            max-struct-bools
diff --git a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
index 0e82fb20e45..bc8e8c1f070 100644
--- a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
+++ b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
@@ -66,8 +66,21 @@ fn main() {
     }
 }
 
-#[test]
-fn test() {
-    let boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]);
-    let _ = boxed_slice.get(1).unwrap();
+#[cfg(test)]
+mod issue9612 {
+    // should not lint in `#[cfg(test)]` modules
+    #[test]
+    fn test_fn() {
+        let _a: u8 = 2.try_into().unwrap();
+        let _a: u8 = 3.try_into().expect("");
+
+        util();
+    }
+
+    fn util() {
+        let _a: u8 = 4.try_into().unwrap();
+        let _a: u8 = 5.try_into().expect("");
+        // should still warn
+        let _ = Box::new([0]).get(1).unwrap();
+    }
 }
diff --git a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
index 681b5eaf54d..94b5ef663ad 100644
--- a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
+++ b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![deny(clippy::get_unwrap)]
    |         ^^^^^^^^^^^^^^^^^^
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:35:17
    |
 LL |         let _ = boxed_slice.get(1).unwrap();
@@ -25,7 +25,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co
 LL |         let _ = some_slice.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:36:17
    |
 LL |         let _ = some_slice.get(0).unwrap();
@@ -39,7 +39,7 @@ error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more conc
 LL |         let _ = some_vec.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:37:17
    |
 LL |         let _ = some_vec.get(0).unwrap();
@@ -53,7 +53,7 @@ error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more
 LL |         let _ = some_vecdeque.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:38:17
    |
 LL |         let _ = some_vecdeque.get(0).unwrap();
@@ -67,7 +67,7 @@ error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more
 LL |         let _ = some_hashmap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:39:17
    |
 LL |         let _ = some_hashmap.get(&1).unwrap();
@@ -81,7 +81,7 @@ error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more
 LL |         let _ = some_btreemap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:40:17
    |
 LL |         let _ = some_btreemap.get(&1).unwrap();
@@ -95,7 +95,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:44:22
    |
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
@@ -109,7 +109,7 @@ error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and mor
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:49:10
    |
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
@@ -123,7 +123,7 @@ error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and mor
 LL |         *some_slice.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:50:10
    |
 LL |         *some_slice.get_mut(0).unwrap() = 1;
@@ -137,7 +137,7 @@ error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more
 LL |         *some_vec.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:51:10
    |
 LL |         *some_vec.get_mut(0).unwrap() = 1;
@@ -151,7 +151,7 @@ error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:52:10
    |
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
@@ -165,7 +165,7 @@ error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more conc
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:64:17
    |
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
@@ -179,7 +179,7 @@ error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:65:17
    |
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
@@ -188,10 +188,10 @@ LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:72:13
+  --> $DIR/unwrap_used.rs:84:17
    |
-LL |     let _ = boxed_slice.get(1).unwrap();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]`
+LL |         let _ = Box::new([0]).get(1).unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&Box::new([0])[1]`
 
 error: aborting due to 27 previous errors
 
diff --git a/src/tools/clippy/tests/ui-toml/vec_box_sized/test.rs b/src/tools/clippy/tests/ui-toml/vec_box_sized/test.rs
index bf04bee1637..4c46deb585b 100644
--- a/src/tools/clippy/tests/ui-toml/vec_box_sized/test.rs
+++ b/src/tools/clippy/tests/ui-toml/vec_box_sized/test.rs
@@ -7,8 +7,9 @@ struct C {
 }
 
 struct Foo(Vec<Box<u8>>);
-struct Bar(Vec<Box<u32>>);
-struct Baz(Vec<Box<(u32, u32)>>);
+struct Bar(Vec<Box<u16>>);
+struct Quux(Vec<Box<u32>>);
+struct Baz(Vec<Box<(u16, u16)>>);
 struct BarBaz(Vec<Box<S>>);
 struct FooBarBaz(Vec<Box<C>>);
 
diff --git a/src/tools/clippy/tests/ui-toml/vec_box_sized/test.stderr b/src/tools/clippy/tests/ui-toml/vec_box_sized/test.stderr
index cf194de3c55..55de68f8ecf 100644
--- a/src/tools/clippy/tests/ui-toml/vec_box_sized/test.stderr
+++ b/src/tools/clippy/tests/ui-toml/vec_box_sized/test.stderr
@@ -9,11 +9,11 @@ LL | struct Foo(Vec<Box<u8>>);
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
   --> $DIR/test.rs:10:12
    |
-LL | struct Bar(Vec<Box<u32>>);
-   |            ^^^^^^^^^^^^^ help: try: `Vec<u32>`
+LL | struct Bar(Vec<Box<u16>>);
+   |            ^^^^^^^^^^^^^ help: try: `Vec<u16>`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/test.rs:13:18
+  --> $DIR/test.rs:14:18
    |
 LL | struct FooBarBaz(Vec<Box<C>>);
    |                  ^^^^^^^^^^^ help: try: `Vec<C>`
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index b25e68f1306..b5ed8988a51 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -150,8 +150,12 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
     _n = 23 + 85;
 
     // Unary
-    _n = -1;
-    _n = -(-1);
+    _n = -2147483647;
+    _n = -i32::MAX;
+    _n = -i32::MIN;
+    _n = -&2147483647;
+    _n = -&i32::MAX;
+    _n = -&i32::MIN;
 }
 
 pub fn runtime_ops() {
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
index 0f06e22bae9..0259a0824e7 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
@@ -19,331 +19,331 @@ LL |     let _ = inferred_string + "";
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:161:5
+  --> $DIR/arithmetic_side_effects.rs:165:5
    |
 LL |     _n += 1;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:162:5
+  --> $DIR/arithmetic_side_effects.rs:166:5
    |
 LL |     _n += &1;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:163:5
+  --> $DIR/arithmetic_side_effects.rs:167:5
    |
 LL |     _n -= 1;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:164:5
+  --> $DIR/arithmetic_side_effects.rs:168:5
    |
 LL |     _n -= &1;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:165:5
+  --> $DIR/arithmetic_side_effects.rs:169:5
    |
 LL |     _n /= 0;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:166:5
+  --> $DIR/arithmetic_side_effects.rs:170:5
    |
 LL |     _n /= &0;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:167:5
+  --> $DIR/arithmetic_side_effects.rs:171:5
    |
 LL |     _n %= 0;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:168:5
+  --> $DIR/arithmetic_side_effects.rs:172:5
    |
 LL |     _n %= &0;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:169:5
+  --> $DIR/arithmetic_side_effects.rs:173:5
    |
 LL |     _n *= 2;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:170:5
+  --> $DIR/arithmetic_side_effects.rs:174:5
    |
 LL |     _n *= &2;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:173:10
+  --> $DIR/arithmetic_side_effects.rs:177:10
    |
 LL |     _n = _n + 1;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:174:10
+  --> $DIR/arithmetic_side_effects.rs:178:10
    |
 LL |     _n = _n + &1;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:175:10
+  --> $DIR/arithmetic_side_effects.rs:179:10
    |
 LL |     _n = 1 + _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:176:10
+  --> $DIR/arithmetic_side_effects.rs:180:10
    |
 LL |     _n = &1 + _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:177:10
+  --> $DIR/arithmetic_side_effects.rs:181:10
    |
 LL |     _n = _n - 1;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:178:10
+  --> $DIR/arithmetic_side_effects.rs:182:10
    |
 LL |     _n = _n - &1;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:179:10
+  --> $DIR/arithmetic_side_effects.rs:183:10
    |
 LL |     _n = 1 - _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:180:10
+  --> $DIR/arithmetic_side_effects.rs:184:10
    |
 LL |     _n = &1 - _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:181:10
+  --> $DIR/arithmetic_side_effects.rs:185:10
    |
 LL |     _n = _n / 0;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:182:10
+  --> $DIR/arithmetic_side_effects.rs:186:10
    |
 LL |     _n = _n / &0;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:183:10
+  --> $DIR/arithmetic_side_effects.rs:187:10
    |
 LL |     _n = _n % 0;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:184:10
+  --> $DIR/arithmetic_side_effects.rs:188:10
    |
 LL |     _n = _n % &0;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:185:10
+  --> $DIR/arithmetic_side_effects.rs:189:10
    |
 LL |     _n = _n * 2;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:186:10
+  --> $DIR/arithmetic_side_effects.rs:190:10
    |
 LL |     _n = _n * &2;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:187:10
+  --> $DIR/arithmetic_side_effects.rs:191:10
    |
 LL |     _n = 2 * _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:188:10
+  --> $DIR/arithmetic_side_effects.rs:192:10
    |
 LL |     _n = &2 * _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:189:10
+  --> $DIR/arithmetic_side_effects.rs:193:10
    |
 LL |     _n = 23 + &85;
    |          ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:190:10
+  --> $DIR/arithmetic_side_effects.rs:194:10
    |
 LL |     _n = &23 + 85;
    |          ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:191:10
+  --> $DIR/arithmetic_side_effects.rs:195:10
    |
 LL |     _n = &23 + &85;
    |          ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:194:13
+  --> $DIR/arithmetic_side_effects.rs:198:13
    |
 LL |     let _ = Custom + 0;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:195:13
+  --> $DIR/arithmetic_side_effects.rs:199:13
    |
 LL |     let _ = Custom + 1;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:196:13
+  --> $DIR/arithmetic_side_effects.rs:200:13
    |
 LL |     let _ = Custom + 2;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:197:13
+  --> $DIR/arithmetic_side_effects.rs:201:13
    |
 LL |     let _ = Custom + 0.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:198:13
+  --> $DIR/arithmetic_side_effects.rs:202:13
    |
 LL |     let _ = Custom + 1.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:199:13
+  --> $DIR/arithmetic_side_effects.rs:203:13
    |
 LL |     let _ = Custom + 2.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:200:13
+  --> $DIR/arithmetic_side_effects.rs:204:13
    |
 LL |     let _ = Custom - 0;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:201:13
+  --> $DIR/arithmetic_side_effects.rs:205:13
    |
 LL |     let _ = Custom - 1;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:202:13
+  --> $DIR/arithmetic_side_effects.rs:206:13
    |
 LL |     let _ = Custom - 2;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:203:13
+  --> $DIR/arithmetic_side_effects.rs:207:13
    |
 LL |     let _ = Custom - 0.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:204:13
+  --> $DIR/arithmetic_side_effects.rs:208:13
    |
 LL |     let _ = Custom - 1.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:205:13
+  --> $DIR/arithmetic_side_effects.rs:209:13
    |
 LL |     let _ = Custom - 2.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:206:13
+  --> $DIR/arithmetic_side_effects.rs:210:13
    |
 LL |     let _ = Custom / 0;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:207:13
+  --> $DIR/arithmetic_side_effects.rs:211:13
    |
 LL |     let _ = Custom / 1;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:208:13
+  --> $DIR/arithmetic_side_effects.rs:212:13
    |
 LL |     let _ = Custom / 2;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:209:13
+  --> $DIR/arithmetic_side_effects.rs:213:13
    |
 LL |     let _ = Custom / 0.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:210:13
+  --> $DIR/arithmetic_side_effects.rs:214:13
    |
 LL |     let _ = Custom / 1.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:211:13
+  --> $DIR/arithmetic_side_effects.rs:215:13
    |
 LL |     let _ = Custom / 2.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:212:13
+  --> $DIR/arithmetic_side_effects.rs:216:13
    |
 LL |     let _ = Custom * 0;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:213:13
+  --> $DIR/arithmetic_side_effects.rs:217:13
    |
 LL |     let _ = Custom * 1;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:214:13
+  --> $DIR/arithmetic_side_effects.rs:218:13
    |
 LL |     let _ = Custom * 2;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:215:13
+  --> $DIR/arithmetic_side_effects.rs:219:13
    |
 LL |     let _ = Custom * 0.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:216:13
+  --> $DIR/arithmetic_side_effects.rs:220:13
    |
 LL |     let _ = Custom * 1.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:217:13
+  --> $DIR/arithmetic_side_effects.rs:221:13
    |
 LL |     let _ = Custom * 2.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:220:10
+  --> $DIR/arithmetic_side_effects.rs:224:10
    |
 LL |     _n = -_n;
    |          ^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:221:10
+  --> $DIR/arithmetic_side_effects.rs:225:10
    |
 LL |     _n = -&_n;
    |          ^^^^
diff --git a/src/tools/clippy/tests/ui/author/blocks.stdout b/src/tools/clippy/tests/ui/author/blocks.stdout
index 9de0550d81d..c6acf24c21e 100644
--- a/src/tools/clippy/tests/ui/author/blocks.stdout
+++ b/src/tools/clippy/tests/ui/author/blocks.stdout
@@ -45,7 +45,7 @@ if let ExprKind::Closure(CaptureBy::Value, fn_decl, body_id, _, None) = expr.kin
     && expr1 = &cx.tcx.hir().body(body_id).value
     && let ExprKind::Call(func, args) = expr1.kind
     && let ExprKind::Path(ref qpath) = func.kind
-    && matches!(qpath, QPath::LangItem(LangItem::FromGenerator, _))
+    && matches!(qpath, QPath::LangItem(LangItem::IdentityFuture, _))
     && args.len() == 1
     && let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = args[0].kind
     && let FnRetTy::DefaultReturn(_) = fn_decl1.output
diff --git a/src/tools/clippy/tests/ui/auxiliary/doc_unsafe_macros.rs b/src/tools/clippy/tests/ui/auxiliary/doc_unsafe_macros.rs
index 869672d1eda..3d917e3dc75 100644
--- a/src/tools/clippy/tests/ui/auxiliary/doc_unsafe_macros.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/doc_unsafe_macros.rs
@@ -6,3 +6,11 @@ macro_rules! undocd_unsafe {
         }
     };
 }
+#[macro_export]
+macro_rules! undocd_safe {
+    () => {
+        pub fn vey_oy() {
+            unimplemented!();
+        }
+    };
+}
diff --git a/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.rs b/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.rs
index d055f17526b..554745368bc 100644
--- a/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.rs
+++ b/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.rs
@@ -1,3 +1,5 @@
+// compile-flags: -W clippy::restriction
+
 #![warn(clippy::blanket_clippy_restriction_lints)]
 
 //! Test that the whole restriction group is not enabled
diff --git a/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr b/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr
index e83eb4d605a..2bf89ab69a4 100644
--- a/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr
+++ b/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr
@@ -1,27 +1,32 @@
-error: restriction lints are not meant to be all enabled
-  --> $DIR/blanket_clippy_restriction_lints.rs:4:9
+error: `clippy::restriction` is not meant to be enabled as a group
+   |
+   = note: because of the command line `--warn clippy::restriction`
+   = help: enable the restriction lints you need individually
+   = note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
+
+error: `clippy::restriction` is not meant to be enabled as a group
+  --> $DIR/blanket_clippy_restriction_lints.rs:6:9
    |
 LL | #![warn(clippy::restriction)]
    |         ^^^^^^^^^^^^^^^^^^^
    |
-   = help: try enabling only the lints you really need
-   = note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
+   = help: enable the restriction lints you need individually
 
-error: restriction lints are not meant to be all enabled
-  --> $DIR/blanket_clippy_restriction_lints.rs:5:9
+error: `clippy::restriction` is not meant to be enabled as a group
+  --> $DIR/blanket_clippy_restriction_lints.rs:7:9
    |
 LL | #![deny(clippy::restriction)]
    |         ^^^^^^^^^^^^^^^^^^^
    |
-   = help: try enabling only the lints you really need
+   = help: enable the restriction lints you need individually
 
-error: restriction lints are not meant to be all enabled
-  --> $DIR/blanket_clippy_restriction_lints.rs:6:11
+error: `clippy::restriction` is not meant to be enabled as a group
+  --> $DIR/blanket_clippy_restriction_lints.rs:8:11
    |
 LL | #![forbid(clippy::restriction)]
    |           ^^^^^^^^^^^^^^^^^^^
    |
-   = help: try enabling only the lints you really need
+   = help: enable the restriction lints you need individually
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed b/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
index 2c8339cdd7f..37d3e3286a4 100644
--- a/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
+++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
@@ -1,5 +1,6 @@
 // run-rustfix
 
+#![feature(let_chains)]
 #![warn(clippy::bool_to_int_with_if)]
 #![allow(unused, dead_code, clippy::unnecessary_operation, clippy::no_effect)]
 
@@ -76,6 +77,8 @@ fn main() {
         123
     };
 
+    pub const SHOULD_NOT_LINT: usize = if true { 1 } else { 0 };
+
     some_fn(a);
 }
 
@@ -89,3 +92,22 @@ fn side_effect() {}
 fn cond(a: bool, b: bool) -> bool {
     a || b
 }
+
+enum Enum {
+    A,
+    B,
+}
+
+fn if_let(a: Enum, b: Enum) {
+    if let Enum::A = a {
+        1
+    } else {
+        0
+    };
+
+    if let Enum::A = a && let Enum::B = b {
+        1
+    } else {
+        0
+    };
+}
diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.rs b/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
index 5d9496f0177..ebdf86fd185 100644
--- a/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
+++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
@@ -1,5 +1,6 @@
 // run-rustfix
 
+#![feature(let_chains)]
 #![warn(clippy::bool_to_int_with_if)]
 #![allow(unused, dead_code, clippy::unnecessary_operation, clippy::no_effect)]
 
@@ -108,6 +109,8 @@ fn main() {
         123
     };
 
+    pub const SHOULD_NOT_LINT: usize = if true { 1 } else { 0 };
+
     some_fn(a);
 }
 
@@ -121,3 +124,22 @@ fn side_effect() {}
 fn cond(a: bool, b: bool) -> bool {
     a || b
 }
+
+enum Enum {
+    A,
+    B,
+}
+
+fn if_let(a: Enum, b: Enum) {
+    if let Enum::A = a {
+        1
+    } else {
+        0
+    };
+
+    if let Enum::A = a && let Enum::B = b {
+        1
+    } else {
+        0
+    };
+}
diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr b/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr
index 4cb5531bef6..5cfb75cc0df 100644
--- a/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr
+++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr
@@ -1,5 +1,5 @@
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:15:5
+  --> $DIR/bool_to_int_with_if.rs:16:5
    |
 LL | /     if a {
 LL | |         1
@@ -12,7 +12,7 @@ LL | |     };
    = note: `-D clippy::bool-to-int-with-if` implied by `-D warnings`
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:20:5
+  --> $DIR/bool_to_int_with_if.rs:21:5
    |
 LL | /     if a {
 LL | |         0
@@ -24,7 +24,7 @@ LL | |     };
    = note: `!a as i32` or `(!a).into()` can also be valid options
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:25:5
+  --> $DIR/bool_to_int_with_if.rs:26:5
    |
 LL | /     if !a {
 LL | |         1
@@ -36,7 +36,7 @@ LL | |     };
    = note: `!a as i32` or `(!a).into()` can also be valid options
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:30:5
+  --> $DIR/bool_to_int_with_if.rs:31:5
    |
 LL | /     if a || b {
 LL | |         1
@@ -48,7 +48,7 @@ LL | |     };
    = note: `(a || b) as i32` or `(a || b).into()` can also be valid options
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:35:5
+  --> $DIR/bool_to_int_with_if.rs:36:5
    |
 LL | /     if cond(a, b) {
 LL | |         1
@@ -60,7 +60,7 @@ LL | |     };
    = note: `cond(a, b) as i32` or `cond(a, b).into()` can also be valid options
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:40:5
+  --> $DIR/bool_to_int_with_if.rs:41:5
    |
 LL | /     if x + y < 4 {
 LL | |         1
@@ -72,7 +72,7 @@ LL | |     };
    = note: `(x + y < 4) as i32` or `(x + y < 4).into()` can also be valid options
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:49:12
+  --> $DIR/bool_to_int_with_if.rs:50:12
    |
 LL |       } else if b {
    |  ____________^
@@ -85,7 +85,7 @@ LL | |     };
    = note: `b as i32` or `b.into()` can also be valid options
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:58:12
+  --> $DIR/bool_to_int_with_if.rs:59:12
    |
 LL |       } else if b {
    |  ____________^
@@ -98,7 +98,7 @@ LL | |     };
    = note: `!b as i32` or `(!b).into()` can also be valid options
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:116:5
+  --> $DIR/bool_to_int_with_if.rs:119:5
    |
 LL |     if a { 1 } else { 0 }
    |     ^^^^^^^^^^^^^^^^^^^^^ help: replace with from: `u8::from(a)`
diff --git a/src/tools/clippy/tests/ui/cognitive_complexity.rs b/src/tools/clippy/tests/ui/cognitive_complexity.rs
index 912e6788afd..07bdaff00dc 100644
--- a/src/tools/clippy/tests/ui/cognitive_complexity.rs
+++ b/src/tools/clippy/tests/ui/cognitive_complexity.rs
@@ -393,3 +393,19 @@ impl Moo {
         }
     }
 }
+
+#[clippy::cognitive_complexity = "1"]
+mod issue9300 {
+    async fn a() {
+        let a = 0;
+        if a == 0 {}
+    }
+
+    pub struct S;
+    impl S {
+        pub async fn async_method() {
+            let a = 0;
+            if a == 0 {}
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/cognitive_complexity.stderr b/src/tools/clippy/tests/ui/cognitive_complexity.stderr
index d7f2f24e52f..5824631fa83 100644
--- a/src/tools/clippy/tests/ui/cognitive_complexity.stderr
+++ b/src/tools/clippy/tests/ui/cognitive_complexity.stderr
@@ -135,5 +135,21 @@ LL |     fn moo(&self) {
    |
    = help: you could split it up into multiple smaller functions
 
-error: aborting due to 17 previous errors
+error: the function has a cognitive complexity of (2/1)
+  --> $DIR/cognitive_complexity.rs:399:14
+   |
+LL |     async fn a() {
+   |              ^
+   |
+   = help: you could split it up into multiple smaller functions
+
+error: the function has a cognitive complexity of (2/1)
+  --> $DIR/cognitive_complexity.rs:406:22
+   |
+LL |         pub async fn async_method() {
+   |                      ^^^^^^^^^^^^
+   |
+   = help: you could split it up into multiple smaller functions
+
+error: aborting due to 19 previous errors
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-2774.stderr b/src/tools/clippy/tests/ui/crashes/ice-2774.stderr
index 0c2d48f938f..1f26c7f4db6 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-2774.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-2774.stderr
@@ -1,4 +1,4 @@
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+error: the following explicit lifetimes could be elided: 'a
   --> $DIR/ice-2774.rs:15:1
    |
 LL | pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) {
diff --git a/src/tools/clippy/tests/ui/crashes/ice-9746.rs b/src/tools/clippy/tests/ui/crashes/ice-9746.rs
new file mode 100644
index 00000000000..fbd373c70bf
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-9746.rs
@@ -0,0 +1,15 @@
+//! <https://github.com/rust-lang/rust-clippy/issues/9746#issuecomment-1297132880>
+
+trait Trait {}
+
+struct Struct<'a> {
+    _inner: &'a Struct<'a>,
+}
+
+impl Trait for Struct<'_> {}
+
+fn example<'a>(s: &'a Struct) -> Box<Box<dyn Trait + 'a>> {
+    Box::new(Box::new(Struct { _inner: s }))
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr b/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
index d68bbe78802..875d5ab4f21 100644
--- a/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
+++ b/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
@@ -1,4 +1,4 @@
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+error: the following explicit lifetimes could be elided: 'a
   --> $DIR/needless_lifetimes_impl_trait.rs:15:5
    |
 LL |     fn baz<'a>(&'a self) -> impl Foo + 'a {
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs
index 4a5c597dda5..e1c9fe30a9d 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs
+++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs
@@ -1,6 +1,5 @@
 // compile-flags: -Clink-arg=-nostartfiles
 // ignore-macos
-// ignore-windows
 
 #![feature(lang_items, start, libc)]
 #![no_std]
diff --git a/src/tools/clippy/tests/ui/doc_errors.stderr b/src/tools/clippy/tests/ui/doc_errors.stderr
index c7b616e2897..d74f2dbfe1b 100644
--- a/src/tools/clippy/tests/ui/doc_errors.stderr
+++ b/src/tools/clippy/tests/ui/doc_errors.stderr
@@ -1,52 +1,40 @@
 error: docs for function returning `Result` missing `# Errors` section
   --> $DIR/doc_errors.rs:7:1
    |
-LL | / pub fn pub_fn_missing_errors_header() -> Result<(), ()> {
-LL | |     unimplemented!();
-LL | | }
-   | |_^
+LL | pub fn pub_fn_missing_errors_header() -> Result<(), ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::missing-errors-doc` implied by `-D warnings`
 
 error: docs for function returning `Result` missing `# Errors` section
   --> $DIR/doc_errors.rs:11:1
    |
-LL | / pub async fn async_pub_fn_missing_errors_header() -> Result<(), ()> {
-LL | |     unimplemented!();
-LL | | }
-   | |_^
+LL | pub async fn async_pub_fn_missing_errors_header() -> Result<(), ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: docs for function returning `Result` missing `# Errors` section
   --> $DIR/doc_errors.rs:16:1
    |
-LL | / pub fn pub_fn_returning_io_result() -> io::Result<()> {
-LL | |     unimplemented!();
-LL | | }
-   | |_^
+LL | pub fn pub_fn_returning_io_result() -> io::Result<()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: docs for function returning `Result` missing `# Errors` section
   --> $DIR/doc_errors.rs:21:1
    |
-LL | / pub async fn async_pub_fn_returning_io_result() -> io::Result<()> {
-LL | |     unimplemented!();
-LL | | }
-   | |_^
+LL | pub async fn async_pub_fn_returning_io_result() -> io::Result<()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: docs for function returning `Result` missing `# Errors` section
   --> $DIR/doc_errors.rs:51:5
    |
-LL | /     pub fn pub_method_missing_errors_header() -> Result<(), ()> {
-LL | |         unimplemented!();
-LL | |     }
-   | |_____^
+LL |     pub fn pub_method_missing_errors_header() -> Result<(), ()> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: docs for function returning `Result` missing `# Errors` section
   --> $DIR/doc_errors.rs:56:5
    |
-LL | /     pub async fn async_pub_method_missing_errors_header() -> Result<(), ()> {
-LL | |         unimplemented!();
-LL | |     }
-   | |_____^
+LL |     pub async fn async_pub_method_missing_errors_header() -> Result<(), ()> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: docs for function returning `Result` missing `# Errors` section
   --> $DIR/doc_errors.rs:85:5
diff --git a/src/tools/clippy/tests/ui/doc_unnecessary_unsafe.rs b/src/tools/clippy/tests/ui/doc_unnecessary_unsafe.rs
new file mode 100644
index 00000000000..d9e9363b0f4
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc_unnecessary_unsafe.rs
@@ -0,0 +1,148 @@
+// aux-build:doc_unsafe_macros.rs
+
+#![allow(clippy::let_unit_value)]
+
+#[macro_use]
+extern crate doc_unsafe_macros;
+
+/// This is has no safety section, and does not need one either
+pub fn destroy_the_planet() {
+    unimplemented!();
+}
+
+/// This one does not need a `Safety` section
+///
+/// # Safety
+///
+/// This function shouldn't be called unless the horsemen are ready
+pub fn apocalypse(universe: &mut ()) {
+    unimplemented!();
+}
+
+/// This is a private function, skip to match behavior with `missing_safety_doc`.
+///
+/// # Safety
+///
+/// Boo!
+fn you_dont_see_me() {
+    unimplemented!();
+}
+
+mod private_mod {
+    /// This is public but unexported function, skip to match behavior with `missing_safety_doc`.
+    ///
+    /// # Safety
+    ///
+    /// Very safe!
+    pub fn only_crate_wide_accessible() {
+        unimplemented!();
+    }
+
+    /// # Safety
+    ///
+    /// Unnecessary safety!
+    pub fn republished() {
+        unimplemented!();
+    }
+}
+
+pub use private_mod::republished;
+
+pub trait SafeTraitSafeMethods {
+    fn woefully_underdocumented(self);
+
+    /// # Safety
+    ///
+    /// Unnecessary!
+    fn documented(self);
+}
+
+pub trait SafeTrait {
+    fn method();
+}
+
+/// # Safety
+///
+/// Unnecessary!
+pub trait DocumentedSafeTrait {
+    fn method2();
+}
+
+pub struct Struct;
+
+impl SafeTraitSafeMethods for Struct {
+    fn woefully_underdocumented(self) {
+        // all is well
+    }
+
+    fn documented(self) {
+        // all is still well
+    }
+}
+
+impl SafeTrait for Struct {
+    fn method() {}
+}
+
+impl DocumentedSafeTrait for Struct {
+    fn method2() {}
+}
+
+impl Struct {
+    /// # Safety
+    ///
+    /// Unnecessary!
+    pub fn documented() -> Self {
+        unimplemented!();
+    }
+
+    pub fn undocumented(&self) {
+        unimplemented!();
+    }
+
+    /// Private, fine again to stay consistent with `missing_safety_doc`.
+    ///
+    /// # Safety
+    ///
+    /// Unnecessary!
+    fn private(&self) {
+        unimplemented!();
+    }
+}
+
+macro_rules! very_safe {
+    () => {
+        pub fn whee() {
+            unimplemented!()
+        }
+
+        /// # Safety
+        ///
+        /// Driving is very safe already!
+        pub fn drive() {
+            whee()
+        }
+    };
+}
+
+very_safe!();
+
+// we don't lint code from external macros
+undocd_safe!();
+
+fn main() {}
+
+// do not lint if any parent has `#[doc(hidden)]` attribute
+// see #7347
+#[doc(hidden)]
+pub mod __macro {
+    pub struct T;
+    impl T {
+        pub unsafe fn f() {}
+    }
+}
+
+/// # Implementation safety
+pub trait DocumentedSafeTraitWithImplementationHeader {
+    fn method();
+}
diff --git a/src/tools/clippy/tests/ui/doc_unnecessary_unsafe.stderr b/src/tools/clippy/tests/ui/doc_unnecessary_unsafe.stderr
new file mode 100644
index 00000000000..83b2efbb346
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc_unnecessary_unsafe.stderr
@@ -0,0 +1,51 @@
+error: safe function's docs have unnecessary `# Safety` section
+  --> $DIR/doc_unnecessary_unsafe.rs:18:1
+   |
+LL | pub fn apocalypse(universe: &mut ()) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::unnecessary-safety-doc` implied by `-D warnings`
+
+error: safe function's docs have unnecessary `# Safety` section
+  --> $DIR/doc_unnecessary_unsafe.rs:44:5
+   |
+LL |     pub fn republished() {
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: safe function's docs have unnecessary `# Safety` section
+  --> $DIR/doc_unnecessary_unsafe.rs:57:5
+   |
+LL |     fn documented(self);
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: docs for safe trait have unnecessary `# Safety` section
+  --> $DIR/doc_unnecessary_unsafe.rs:67:1
+   |
+LL | pub trait DocumentedSafeTrait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: safe function's docs have unnecessary `# Safety` section
+  --> $DIR/doc_unnecessary_unsafe.rs:95:5
+   |
+LL |     pub fn documented() -> Self {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: safe function's docs have unnecessary `# Safety` section
+  --> $DIR/doc_unnecessary_unsafe.rs:122:9
+   |
+LL |         pub fn drive() {
+   |         ^^^^^^^^^^^^^^
+...
+LL | very_safe!();
+   | ------------ in this macro invocation
+   |
+   = note: this error originates in the macro `very_safe` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: docs for safe trait have unnecessary `# Safety` section
+  --> $DIR/doc_unnecessary_unsafe.rs:146:1
+   |
+LL | pub trait DocumentedSafeTraitWithImplementationHeader {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/doc_unsafe.stderr b/src/tools/clippy/tests/ui/doc_unsafe.stderr
index 904b88eaef6..a86e191370e 100644
--- a/src/tools/clippy/tests/ui/doc_unsafe.stderr
+++ b/src/tools/clippy/tests/ui/doc_unsafe.stderr
@@ -1,20 +1,16 @@
 error: unsafe function's docs miss `# Safety` section
   --> $DIR/doc_unsafe.rs:9:1
    |
-LL | / pub unsafe fn destroy_the_planet() {
-LL | |     unimplemented!();
-LL | | }
-   | |_^
+LL | pub unsafe fn destroy_the_planet() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::missing-safety-doc` implied by `-D warnings`
 
 error: unsafe function's docs miss `# Safety` section
   --> $DIR/doc_unsafe.rs:32:5
    |
-LL | /     pub unsafe fn republished() {
-LL | |         unimplemented!();
-LL | |     }
-   | |_____^
+LL |     pub unsafe fn republished() {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unsafe function's docs miss `# Safety` section
   --> $DIR/doc_unsafe.rs:40:5
@@ -25,29 +21,23 @@ LL |     unsafe fn woefully_underdocumented(self);
 error: docs for unsafe trait missing `# Safety` section
   --> $DIR/doc_unsafe.rs:46:1
    |
-LL | / pub unsafe trait UnsafeTrait {
-LL | |     fn method();
-LL | | }
-   | |_^
+LL | pub unsafe trait UnsafeTrait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unsafe function's docs miss `# Safety` section
   --> $DIR/doc_unsafe.rs:76:5
    |
-LL | /     pub unsafe fn more_undocumented_unsafe() -> Self {
-LL | |         unimplemented!();
-LL | |     }
-   | |_____^
+LL |     pub unsafe fn more_undocumented_unsafe() -> Self {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unsafe function's docs miss `# Safety` section
   --> $DIR/doc_unsafe.rs:92:9
    |
-LL | /         pub unsafe fn whee() {
-LL | |             unimplemented!()
-LL | |         }
-   | |_________^
+LL |         pub unsafe fn whee() {
+   |         ^^^^^^^^^^^^^^^^^^^^
 ...
-LL |   very_unsafe!();
-   |   -------------- in this macro invocation
+LL | very_unsafe!();
+   | -------------- in this macro invocation
    |
    = note: this error originates in the macro `very_unsafe` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/tools/clippy/tests/ui/eq_op.rs b/src/tools/clippy/tests/ui/eq_op.rs
index 422f9486503..e7379550265 100644
--- a/src/tools/clippy/tests/ui/eq_op.rs
+++ b/src/tools/clippy/tests/ui/eq_op.rs
@@ -2,6 +2,7 @@
 
 #![warn(clippy::eq_op)]
 #![allow(clippy::double_parens, clippy::identity_op, clippy::nonminimal_bool)]
+#![allow(clippy::suspicious_xor_used_as_pow)]
 
 fn main() {
     // simple values and comparisons
diff --git a/src/tools/clippy/tests/ui/eq_op.stderr b/src/tools/clippy/tests/ui/eq_op.stderr
index 313ceed2b41..d365ab27edc 100644
--- a/src/tools/clippy/tests/ui/eq_op.stderr
+++ b/src/tools/clippy/tests/ui/eq_op.stderr
@@ -1,5 +1,5 @@
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:8:13
+  --> $DIR/eq_op.rs:9:13
    |
 LL |     let _ = 1 == 1;
    |             ^^^^^^
@@ -7,163 +7,163 @@ LL |     let _ = 1 == 1;
    = note: `-D clippy::eq-op` implied by `-D warnings`
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:9:13
+  --> $DIR/eq_op.rs:10:13
    |
 LL |     let _ = "no" == "no";
    |             ^^^^^^^^^^^^
 
 error: equal expressions as operands to `!=`
-  --> $DIR/eq_op.rs:11:13
+  --> $DIR/eq_op.rs:12:13
    |
 LL |     let _ = false != false;
    |             ^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `<`
-  --> $DIR/eq_op.rs:12:13
+  --> $DIR/eq_op.rs:13:13
    |
 LL |     let _ = 1.5 < 1.5;
    |             ^^^^^^^^^
 
 error: equal expressions as operands to `>=`
-  --> $DIR/eq_op.rs:13:13
+  --> $DIR/eq_op.rs:14:13
    |
 LL |     let _ = 1u64 >= 1u64;
    |             ^^^^^^^^^^^^
 
 error: equal expressions as operands to `&`
-  --> $DIR/eq_op.rs:16:13
+  --> $DIR/eq_op.rs:17:13
    |
 LL |     let _ = (1u32 as u64) & (1u32 as u64);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `^`
-  --> $DIR/eq_op.rs:19:17
+  --> $DIR/eq_op.rs:20:17
    |
 LL |         let _ = 1 ^ ((((((1))))));
    |                 ^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `<`
-  --> $DIR/eq_op.rs:23:13
+  --> $DIR/eq_op.rs:24:13
    |
 LL |     let _ = (-(2) < -(2));
    |             ^^^^^^^^^^^^^
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:24:13
+  --> $DIR/eq_op.rs:25:13
    |
 LL |     let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `&`
-  --> $DIR/eq_op.rs:24:14
+  --> $DIR/eq_op.rs:25:14
    |
 LL |     let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1));
    |              ^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `&`
-  --> $DIR/eq_op.rs:24:35
+  --> $DIR/eq_op.rs:25:35
    |
 LL |     let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1));
    |                                   ^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:25:13
+  --> $DIR/eq_op.rs:26:13
    |
 LL |     let _ = (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `!=`
-  --> $DIR/eq_op.rs:28:13
+  --> $DIR/eq_op.rs:29:13
    |
 LL |     let _ = ([1] != [1]);
    |             ^^^^^^^^^^^^
 
 error: equal expressions as operands to `!=`
-  --> $DIR/eq_op.rs:29:13
+  --> $DIR/eq_op.rs:30:13
    |
 LL |     let _ = ((1, 2) != (1, 2));
    |             ^^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:33:13
+  --> $DIR/eq_op.rs:34:13
    |
 LL |     let _ = 1 + 1 == 2;
    |             ^^^^^^^^^^
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:34:13
+  --> $DIR/eq_op.rs:35:13
    |
 LL |     let _ = 1 - 1 == 0;
    |             ^^^^^^^^^^
 
 error: equal expressions as operands to `-`
-  --> $DIR/eq_op.rs:34:13
+  --> $DIR/eq_op.rs:35:13
    |
 LL |     let _ = 1 - 1 == 0;
    |             ^^^^^
 
 error: equal expressions as operands to `-`
-  --> $DIR/eq_op.rs:36:13
+  --> $DIR/eq_op.rs:37:13
    |
 LL |     let _ = 1 - 1;
    |             ^^^^^
 
 error: equal expressions as operands to `/`
-  --> $DIR/eq_op.rs:37:13
+  --> $DIR/eq_op.rs:38:13
    |
 LL |     let _ = 1 / 1;
    |             ^^^^^
 
 error: equal expressions as operands to `&&`
-  --> $DIR/eq_op.rs:38:13
+  --> $DIR/eq_op.rs:39:13
    |
 LL |     let _ = true && true;
    |             ^^^^^^^^^^^^
 
 error: equal expressions as operands to `||`
-  --> $DIR/eq_op.rs:40:13
+  --> $DIR/eq_op.rs:41:13
    |
 LL |     let _ = true || true;
    |             ^^^^^^^^^^^^
 
 error: equal expressions as operands to `&&`
-  --> $DIR/eq_op.rs:45:13
+  --> $DIR/eq_op.rs:46:13
    |
 LL |     let _ = a == b && b == a;
    |             ^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `&&`
-  --> $DIR/eq_op.rs:46:13
+  --> $DIR/eq_op.rs:47:13
    |
 LL |     let _ = a != b && b != a;
    |             ^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `&&`
-  --> $DIR/eq_op.rs:47:13
+  --> $DIR/eq_op.rs:48:13
    |
 LL |     let _ = a < b && b > a;
    |             ^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `&&`
-  --> $DIR/eq_op.rs:48:13
+  --> $DIR/eq_op.rs:49:13
    |
 LL |     let _ = a <= b && b >= a;
    |             ^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:51:13
+  --> $DIR/eq_op.rs:52:13
    |
 LL |     let _ = a == a;
    |             ^^^^^^
 
 error: equal expressions as operands to `/`
-  --> $DIR/eq_op.rs:61:20
+  --> $DIR/eq_op.rs:62:20
    |
 LL |     const D: u32 = A / A;
    |                    ^^^^^
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:92:5
+  --> $DIR/eq_op.rs:93:5
    |
 LL |     (n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/equatable_if_let.fixed b/src/tools/clippy/tests/ui/equatable_if_let.fixed
index 687efdada6e..9af2ba96272 100644
--- a/src/tools/clippy/tests/ui/equatable_if_let.fixed
+++ b/src/tools/clippy/tests/ui/equatable_if_let.fixed
@@ -23,6 +23,11 @@ struct Struct {
     b: bool,
 }
 
+struct NoPartialEqStruct {
+    a: i32,
+    b: bool,
+}
+
 enum NotPartialEq {
     A,
     B,
@@ -47,6 +52,7 @@ fn main() {
     let e = Enum::UnitVariant;
     let f = NotPartialEq::A;
     let g = NotStructuralEq::A;
+    let h = NoPartialEqStruct { a: 2, b: false };
 
     // true
 
@@ -66,10 +72,11 @@ fn main() {
     if let Some(3 | 4) = c {}
     if let Struct { a, b: false } = d {}
     if let Struct { a: 2, b: x } = d {}
-    if let NotPartialEq::A = f {}
+    if matches!(f, NotPartialEq::A) {}
     if g == NotStructuralEq::A {}
-    if let Some(NotPartialEq::A) = Some(f) {}
+    if matches!(Some(f), Some(NotPartialEq::A)) {}
     if Some(g) == Some(NotStructuralEq::A) {}
+    if matches!(h, NoPartialEqStruct { a: 2, b: false }) {}
 
     macro_rules! m1 {
         (x) => {
diff --git a/src/tools/clippy/tests/ui/equatable_if_let.rs b/src/tools/clippy/tests/ui/equatable_if_let.rs
index 8c467d14d2a..c3626c081dd 100644
--- a/src/tools/clippy/tests/ui/equatable_if_let.rs
+++ b/src/tools/clippy/tests/ui/equatable_if_let.rs
@@ -23,6 +23,11 @@ struct Struct {
     b: bool,
 }
 
+struct NoPartialEqStruct {
+    a: i32,
+    b: bool,
+}
+
 enum NotPartialEq {
     A,
     B,
@@ -47,6 +52,7 @@ fn main() {
     let e = Enum::UnitVariant;
     let f = NotPartialEq::A;
     let g = NotStructuralEq::A;
+    let h = NoPartialEqStruct { a: 2, b: false };
 
     // true
 
@@ -70,6 +76,7 @@ fn main() {
     if let NotStructuralEq::A = g {}
     if let Some(NotPartialEq::A) = Some(f) {}
     if let Some(NotStructuralEq::A) = Some(g) {}
+    if let NoPartialEqStruct { a: 2, b: false } = h {}
 
     macro_rules! m1 {
         (x) => {
diff --git a/src/tools/clippy/tests/ui/equatable_if_let.stderr b/src/tools/clippy/tests/ui/equatable_if_let.stderr
index 9c4c3cc3682..40ca75b8da2 100644
--- a/src/tools/clippy/tests/ui/equatable_if_let.stderr
+++ b/src/tools/clippy/tests/ui/equatable_if_let.stderr
@@ -1,5 +1,5 @@
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:53:8
+  --> $DIR/equatable_if_let.rs:59:8
    |
 LL |     if let 2 = a {}
    |        ^^^^^^^^^ help: try: `a == 2`
@@ -7,64 +7,82 @@ LL |     if let 2 = a {}
    = note: `-D clippy::equatable-if-let` implied by `-D warnings`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:54:8
+  --> $DIR/equatable_if_let.rs:60:8
    |
 LL |     if let Ordering::Greater = a.cmp(&b) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.cmp(&b) == Ordering::Greater`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:55:8
+  --> $DIR/equatable_if_let.rs:61:8
    |
 LL |     if let Some(2) = c {}
    |        ^^^^^^^^^^^^^^^ help: try: `c == Some(2)`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:56:8
+  --> $DIR/equatable_if_let.rs:62:8
    |
 LL |     if let Struct { a: 2, b: false } = d {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d == (Struct { a: 2, b: false })`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:57:8
+  --> $DIR/equatable_if_let.rs:63:8
    |
 LL |     if let Enum::TupleVariant(32, 64) = e {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::TupleVariant(32, 64)`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:58:8
+  --> $DIR/equatable_if_let.rs:64:8
    |
 LL |     if let Enum::RecordVariant { a: 64, b: 32 } = e {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == (Enum::RecordVariant { a: 64, b: 32 })`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:59:8
+  --> $DIR/equatable_if_let.rs:65:8
    |
 LL |     if let Enum::UnitVariant = e {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:60:8
+  --> $DIR/equatable_if_let.rs:66:8
    |
 LL |     if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false })`
 
+error: this pattern matching can be expressed using `matches!`
+  --> $DIR/equatable_if_let.rs:75:8
+   |
+LL |     if let NotPartialEq::A = f {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(f, NotPartialEq::A)`
+
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:70:8
+  --> $DIR/equatable_if_let.rs:76:8
    |
 LL |     if let NotStructuralEq::A = g {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A`
 
+error: this pattern matching can be expressed using `matches!`
+  --> $DIR/equatable_if_let.rs:77:8
+   |
+LL |     if let Some(NotPartialEq::A) = Some(f) {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(f), Some(NotPartialEq::A))`
+
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:72:8
+  --> $DIR/equatable_if_let.rs:78:8
    |
 LL |     if let Some(NotStructuralEq::A) = Some(g) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)`
 
-error: this pattern matching can be expressed using equality
+error: this pattern matching can be expressed using `matches!`
   --> $DIR/equatable_if_let.rs:79:8
    |
+LL |     if let NoPartialEqStruct { a: 2, b: false } = h {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(h, NoPartialEqStruct { a: 2, b: false })`
+
+error: this pattern matching can be expressed using equality
+  --> $DIR/equatable_if_let.rs:86:8
+   |
 LL |     if let m1!(x) = "abc" {
    |        ^^^^^^^^^^^^^^^^^^ help: try: `"abc" == m1!(x)`
 
-error: aborting due to 11 previous errors
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/clippy/tests/ui/expect.stderr b/src/tools/clippy/tests/ui/expect.stderr
index f6738865cac..c08e0dbbf74 100644
--- a/src/tools/clippy/tests/ui/expect.stderr
+++ b/src/tools/clippy/tests/ui/expect.stderr
@@ -1,4 +1,4 @@
-error: used `expect()` on `an Option` value
+error: used `expect()` on an `Option` value
   --> $DIR/expect.rs:5:13
    |
 LL |     let _ = opt.expect("");
@@ -7,7 +7,7 @@ LL |     let _ = opt.expect("");
    = help: if this value is `None`, it will panic
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
-error: used `expect()` on `a Result` value
+error: used `expect()` on a `Result` value
   --> $DIR/expect.rs:10:13
    |
 LL |     let _ = res.expect("");
@@ -15,7 +15,7 @@ LL |     let _ = res.expect("");
    |
    = help: if this value is an `Err`, it will panic
 
-error: used `expect_err()` on `a Result` value
+error: used `expect_err()` on a `Result` value
   --> $DIR/expect.rs:11:13
    |
 LL |     let _ = res.expect_err("");
diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.fixed b/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
index d1d35e5c0eb..59ff5e4040a 100644
--- a/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
+++ b/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
@@ -266,4 +266,15 @@ fn main() {
         }
         x
     };
+
+    trait WithAssoc {
+        type Assoc: ?Sized;
+    }
+    impl WithAssoc for String {
+        type Assoc = str;
+    }
+    fn takes_assoc<T: WithAssoc>(_: &T::Assoc) -> T {
+        unimplemented!()
+    }
+    let _: String = takes_assoc(&*String::new());
 }
diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.rs b/src/tools/clippy/tests/ui/explicit_auto_deref.rs
index deedafad153..bcfb60c3278 100644
--- a/src/tools/clippy/tests/ui/explicit_auto_deref.rs
+++ b/src/tools/clippy/tests/ui/explicit_auto_deref.rs
@@ -266,4 +266,15 @@ fn main() {
         }
         *x
     };
+
+    trait WithAssoc {
+        type Assoc: ?Sized;
+    }
+    impl WithAssoc for String {
+        type Assoc = str;
+    }
+    fn takes_assoc<T: WithAssoc>(_: &T::Assoc) -> T {
+        unimplemented!()
+    }
+    let _: String = takes_assoc(&*String::new());
 }
diff --git a/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs b/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs
index f805bcc9ba8..f53e531629a 100644
--- a/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs
+++ b/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs
@@ -2,6 +2,7 @@
 #![allow(clippy::too_many_arguments)]
 
 extern "C" {
+    // Should not lint, most of the time users have no control over extern function signatures
     fn f(_: bool, _: bool, _: bool, _: bool);
 }
 
@@ -22,8 +23,12 @@ fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool) {}
 
 struct S;
 trait Trait {
+    // should warn for trait functions with and without body
     fn f(_: bool, _: bool, _: bool, _: bool);
     fn g(_: bool, _: bool, _: bool, _: Vec<u32>);
+    #[allow(clippy::fn_params_excessive_bools)]
+    fn h(_: bool, _: bool, _: bool, _: bool, _: bool, _: bool);
+    fn i(_: bool, _: bool, _: bool, _: bool) {}
 }
 
 impl S {
@@ -34,8 +39,11 @@ impl S {
 }
 
 impl Trait for S {
+    // Should not lint because the trait might not be changeable by the user
+    // We only lint in the trait definition
     fn f(_: bool, _: bool, _: bool, _: bool) {}
     fn g(_: bool, _: bool, _: bool, _: Vec<u32>) {}
+    fn h(_: bool, _: bool, _: bool, _: bool, _: bool, _: bool) {}
 }
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr b/src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr
index 11627105691..43363b46972 100644
--- a/src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr
+++ b/src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr
@@ -1,5 +1,5 @@
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:18:1
+  --> $DIR/fn_params_excessive_bools.rs:19:1
    |
 LL | fn g(_: bool, _: bool, _: bool, _: bool) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | fn g(_: bool, _: bool, _: bool, _: bool) {}
    = note: `-D clippy::fn-params-excessive-bools` implied by `-D warnings`
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:21:1
+  --> $DIR/fn_params_excessive_bools.rs:22:1
    |
 LL | fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL | fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:25:5
+  --> $DIR/fn_params_excessive_bools.rs:27:5
    |
 LL |     fn f(_: bool, _: bool, _: bool, _: bool);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,15 @@ LL |     fn f(_: bool, _: bool, _: bool, _: bool);
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:30:5
+  --> $DIR/fn_params_excessive_bools.rs:31:5
+   |
+LL |     fn i(_: bool, _: bool, _: bool, _: bool) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider refactoring bools into two-variant enums
+
+error: more than 3 bools in function parameters
+  --> $DIR/fn_params_excessive_bools.rs:35:5
    |
 LL |     fn f(&self, _: bool, _: bool, _: bool, _: bool) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -32,7 +40,7 @@ LL |     fn f(&self, _: bool, _: bool, _: bool, _: bool) {}
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:42:5
+  --> $DIR/fn_params_excessive_bools.rs:50:5
    |
 LL | /     fn n(_: bool, _: u32, _: bool, _: Box<u32>, _: bool, _: bool) {
 LL | |         fn nn(_: bool, _: bool, _: bool, _: bool) {}
@@ -42,12 +50,12 @@ LL | |     }
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:43:9
+  --> $DIR/fn_params_excessive_bools.rs:51:9
    |
 LL |         fn nn(_: bool, _: bool, _: bool, _: bool) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider refactoring bools into two-variant enums
 
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/from_raw_with_void_ptr.rs b/src/tools/clippy/tests/ui/from_raw_with_void_ptr.rs
new file mode 100644
index 00000000000..8484da2415a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/from_raw_with_void_ptr.rs
@@ -0,0 +1,34 @@
+#![warn(clippy::from_raw_with_void_ptr)]
+
+use std::ffi::c_void;
+use std::rc::Rc;
+use std::sync::Arc;
+
+fn main() {
+    // must lint
+    let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void;
+    let _ = unsafe { Box::from_raw(ptr) };
+
+    // shouldn't be linted
+    let _ = unsafe { Box::from_raw(ptr as *mut usize) };
+
+    // shouldn't be linted
+    let should_not_lint_ptr = Box::into_raw(Box::new(12u8)) as *mut u8;
+    let _ = unsafe { Box::from_raw(should_not_lint_ptr as *mut u8) };
+
+    // must lint
+    let ptr = Rc::into_raw(Rc::new(42usize)) as *mut c_void;
+    let _ = unsafe { Rc::from_raw(ptr) };
+
+    // must lint
+    let ptr = Arc::into_raw(Arc::new(42usize)) as *mut c_void;
+    let _ = unsafe { Arc::from_raw(ptr) };
+
+    // must lint
+    let ptr = std::rc::Weak::into_raw(Rc::downgrade(&Rc::new(42usize))) as *mut c_void;
+    let _ = unsafe { std::rc::Weak::from_raw(ptr) };
+
+    // must lint
+    let ptr = std::sync::Weak::into_raw(Arc::downgrade(&Arc::new(42usize))) as *mut c_void;
+    let _ = unsafe { std::sync::Weak::from_raw(ptr) };
+}
diff --git a/src/tools/clippy/tests/ui/from_raw_with_void_ptr.stderr b/src/tools/clippy/tests/ui/from_raw_with_void_ptr.stderr
new file mode 100644
index 00000000000..96e4af12ba3
--- /dev/null
+++ b/src/tools/clippy/tests/ui/from_raw_with_void_ptr.stderr
@@ -0,0 +1,63 @@
+error: creating a `Box` from a void raw pointer
+  --> $DIR/from_raw_with_void_ptr.rs:10:22
+   |
+LL |     let _ = unsafe { Box::from_raw(ptr) };
+   |                      ^^^^^^^^^^^^^^^^^^
+   |
+help: cast this to a pointer of the appropriate type
+  --> $DIR/from_raw_with_void_ptr.rs:10:36
+   |
+LL |     let _ = unsafe { Box::from_raw(ptr) };
+   |                                    ^^^
+   = note: `-D clippy::from-raw-with-void-ptr` implied by `-D warnings`
+
+error: creating a `Rc` from a void raw pointer
+  --> $DIR/from_raw_with_void_ptr.rs:21:22
+   |
+LL |     let _ = unsafe { Rc::from_raw(ptr) };
+   |                      ^^^^^^^^^^^^^^^^^
+   |
+help: cast this to a pointer of the appropriate type
+  --> $DIR/from_raw_with_void_ptr.rs:21:35
+   |
+LL |     let _ = unsafe { Rc::from_raw(ptr) };
+   |                                   ^^^
+
+error: creating a `Arc` from a void raw pointer
+  --> $DIR/from_raw_with_void_ptr.rs:25:22
+   |
+LL |     let _ = unsafe { Arc::from_raw(ptr) };
+   |                      ^^^^^^^^^^^^^^^^^^
+   |
+help: cast this to a pointer of the appropriate type
+  --> $DIR/from_raw_with_void_ptr.rs:25:36
+   |
+LL |     let _ = unsafe { Arc::from_raw(ptr) };
+   |                                    ^^^
+
+error: creating a `Weak` from a void raw pointer
+  --> $DIR/from_raw_with_void_ptr.rs:29:22
+   |
+LL |     let _ = unsafe { std::rc::Weak::from_raw(ptr) };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: cast this to a pointer of the appropriate type
+  --> $DIR/from_raw_with_void_ptr.rs:29:46
+   |
+LL |     let _ = unsafe { std::rc::Weak::from_raw(ptr) };
+   |                                              ^^^
+
+error: creating a `Weak` from a void raw pointer
+  --> $DIR/from_raw_with_void_ptr.rs:33:22
+   |
+LL |     let _ = unsafe { std::sync::Weak::from_raw(ptr) };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: cast this to a pointer of the appropriate type
+  --> $DIR/from_raw_with_void_ptr.rs:33:48
+   |
+LL |     let _ = unsafe { std::sync::Weak::from_raw(ptr) };
+   |                                                ^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/tools/clippy/tests/ui/get_unwrap.stderr b/src/tools/clippy/tests/ui/get_unwrap.stderr
index 937f8590408..6dee4d5b4b6 100644
--- a/src/tools/clippy/tests/ui/get_unwrap.stderr
+++ b/src/tools/clippy/tests/ui/get_unwrap.stderr
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![deny(clippy::get_unwrap)]
    |         ^^^^^^^^^^^^^^^^^^
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:35:17
    |
 LL |         let _ = boxed_slice.get(1).unwrap();
@@ -25,7 +25,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co
 LL |         let _ = some_slice.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:36:17
    |
 LL |         let _ = some_slice.get(0).unwrap();
@@ -39,7 +39,7 @@ error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more conc
 LL |         let _ = some_vec.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:37:17
    |
 LL |         let _ = some_vec.get(0).unwrap();
@@ -53,7 +53,7 @@ error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more
 LL |         let _ = some_vecdeque.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:38:17
    |
 LL |         let _ = some_vecdeque.get(0).unwrap();
@@ -67,7 +67,7 @@ error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more
 LL |         let _ = some_hashmap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:39:17
    |
 LL |         let _ = some_hashmap.get(&1).unwrap();
@@ -81,7 +81,7 @@ error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more
 LL |         let _ = some_btreemap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:40:17
    |
 LL |         let _ = some_btreemap.get(&1).unwrap();
@@ -95,7 +95,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:44:22
    |
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
@@ -109,7 +109,7 @@ error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and mor
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:49:10
    |
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
@@ -123,7 +123,7 @@ error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and mor
 LL |         *some_slice.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:50:10
    |
 LL |         *some_slice.get_mut(0).unwrap() = 1;
@@ -137,7 +137,7 @@ error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more
 LL |         *some_vec.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:51:10
    |
 LL |         *some_vec.get_mut(0).unwrap() = 1;
@@ -151,7 +151,7 @@ error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:52:10
    |
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
@@ -165,7 +165,7 @@ error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more conc
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:64:17
    |
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
@@ -179,7 +179,7 @@ error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:65:17
    |
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
diff --git a/src/tools/clippy/tests/ui/infallible_destructuring_match.fixed b/src/tools/clippy/tests/ui/infallible_destructuring_match.fixed
index b8e40d99553..61985e56b76 100644
--- a/src/tools/clippy/tests/ui/infallible_destructuring_match.fixed
+++ b/src/tools/clippy/tests/ui/infallible_destructuring_match.fixed
@@ -9,6 +9,9 @@ enum SingleVariantEnum {
 
 struct TupleStruct(i32);
 
+struct NonCopy;
+struct TupleStructWithNonCopy(NonCopy);
+
 enum EmptyEnum {}
 
 macro_rules! match_enum {
@@ -71,6 +74,15 @@ fn infallible_destructuring_match_struct() {
     let TupleStruct(data) = wrapper;
 }
 
+fn infallible_destructuring_match_struct_with_noncopy() {
+    let wrapper = TupleStructWithNonCopy(NonCopy);
+
+    // This should lint! (keeping `ref` in the suggestion)
+    let TupleStructWithNonCopy(ref data) = wrapper;
+
+    let TupleStructWithNonCopy(ref data) = wrapper;
+}
+
 macro_rules! match_never_enum {
     ($param:expr) => {
         let data = match $param {
diff --git a/src/tools/clippy/tests/ui/infallible_destructuring_match.rs b/src/tools/clippy/tests/ui/infallible_destructuring_match.rs
index 106cd438b90..f2768245bbc 100644
--- a/src/tools/clippy/tests/ui/infallible_destructuring_match.rs
+++ b/src/tools/clippy/tests/ui/infallible_destructuring_match.rs
@@ -9,6 +9,9 @@ enum SingleVariantEnum {
 
 struct TupleStruct(i32);
 
+struct NonCopy;
+struct TupleStructWithNonCopy(NonCopy);
+
 enum EmptyEnum {}
 
 macro_rules! match_enum {
@@ -75,6 +78,17 @@ fn infallible_destructuring_match_struct() {
     let TupleStruct(data) = wrapper;
 }
 
+fn infallible_destructuring_match_struct_with_noncopy() {
+    let wrapper = TupleStructWithNonCopy(NonCopy);
+
+    // This should lint! (keeping `ref` in the suggestion)
+    let data = match wrapper {
+        TupleStructWithNonCopy(ref n) => n,
+    };
+
+    let TupleStructWithNonCopy(ref data) = wrapper;
+}
+
 macro_rules! match_never_enum {
     ($param:expr) => {
         let data = match $param {
diff --git a/src/tools/clippy/tests/ui/infallible_destructuring_match.stderr b/src/tools/clippy/tests/ui/infallible_destructuring_match.stderr
index 1b78db42014..f8a50f0223d 100644
--- a/src/tools/clippy/tests/ui/infallible_destructuring_match.stderr
+++ b/src/tools/clippy/tests/ui/infallible_destructuring_match.stderr
@@ -1,5 +1,5 @@
 error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let`
-  --> $DIR/infallible_destructuring_match.rs:26:5
+  --> $DIR/infallible_destructuring_match.rs:29:5
    |
 LL | /     let data = match wrapper {
 LL | |         SingleVariantEnum::Variant(i) => i,
@@ -9,7 +9,7 @@ LL | |     };
    = note: `-D clippy::infallible-destructuring-match` implied by `-D warnings`
 
 error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let`
-  --> $DIR/infallible_destructuring_match.rs:58:5
+  --> $DIR/infallible_destructuring_match.rs:61:5
    |
 LL | /     let data = match wrapper {
 LL | |         TupleStruct(i) => i,
@@ -17,12 +17,20 @@ LL | |     };
    | |______^ help: try this: `let TupleStruct(data) = wrapper;`
 
 error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let`
-  --> $DIR/infallible_destructuring_match.rs:90:5
+  --> $DIR/infallible_destructuring_match.rs:85:5
+   |
+LL | /     let data = match wrapper {
+LL | |         TupleStructWithNonCopy(ref n) => n,
+LL | |     };
+   | |______^ help: try this: `let TupleStructWithNonCopy(ref data) = wrapper;`
+
+error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let`
+  --> $DIR/infallible_destructuring_match.rs:104:5
    |
 LL | /     let data = match wrapper {
 LL | |         Ok(i) => i,
 LL | |     };
    | |______^ help: try this: `let Ok(data) = wrapper;`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/issue_4266.stderr b/src/tools/clippy/tests/ui/issue_4266.stderr
index fb2a93c9580..fd553aa4538 100644
--- a/src/tools/clippy/tests/ui/issue_4266.stderr
+++ b/src/tools/clippy/tests/ui/issue_4266.stderr
@@ -1,4 +1,4 @@
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+error: the following explicit lifetimes could be elided: 'a
   --> $DIR/issue_4266.rs:4:1
    |
 LL | async fn sink1<'a>(_: &'a str) {} // lint
@@ -6,7 +6,7 @@ LL | async fn sink1<'a>(_: &'a str) {} // lint
    |
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+error: the following explicit lifetimes could be elided: 'a
   --> $DIR/issue_4266.rs:8:1
    |
 LL | async fn one_to_one<'a>(s: &'a str) -> &'a str {
diff --git a/src/tools/clippy/tests/ui/let_underscore_drop.rs b/src/tools/clippy/tests/ui/let_underscore_drop.rs
deleted file mode 100644
index 11b50492ab2..00000000000
--- a/src/tools/clippy/tests/ui/let_underscore_drop.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#![warn(clippy::let_underscore_drop)]
-#![allow(clippy::let_unit_value)]
-
-struct Droppable;
-
-impl Drop for Droppable {
-    fn drop(&mut self) {}
-}
-
-fn main() {
-    let unit = ();
-    let boxed = Box::new(());
-    let droppable = Droppable;
-    let optional = Some(Droppable);
-
-    let _ = ();
-    let _ = Box::new(());
-    let _ = Droppable;
-    let _ = Some(Droppable);
-
-    // no lint for reference
-    let _ = droppable_ref();
-}
-
-#[must_use]
-fn droppable_ref() -> &'static mut Droppable {
-    unimplemented!()
-}
diff --git a/src/tools/clippy/tests/ui/let_underscore_drop.stderr b/src/tools/clippy/tests/ui/let_underscore_drop.stderr
deleted file mode 100644
index 324b7cd431d..00000000000
--- a/src/tools/clippy/tests/ui/let_underscore_drop.stderr
+++ /dev/null
@@ -1,27 +0,0 @@
-error: non-binding `let` on a type that implements `Drop`
-  --> $DIR/let_underscore_drop.rs:17:5
-   |
-LL |     let _ = Box::new(());
-   |     ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-   = note: `-D clippy::let-underscore-drop` implied by `-D warnings`
-
-error: non-binding `let` on a type that implements `Drop`
-  --> $DIR/let_underscore_drop.rs:18:5
-   |
-LL |     let _ = Droppable;
-   |     ^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-
-error: non-binding `let` on a type that implements `Drop`
-  --> $DIR/let_underscore_drop.rs:19:5
-   |
-LL |     let _ = Some(Droppable);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-
-error: aborting due to 3 previous errors
-
diff --git a/src/tools/clippy/tests/ui/let_underscore_future.rs b/src/tools/clippy/tests/ui/let_underscore_future.rs
new file mode 100644
index 00000000000..d8f54cdca91
--- /dev/null
+++ b/src/tools/clippy/tests/ui/let_underscore_future.rs
@@ -0,0 +1,20 @@
+use std::future::Future;
+
+async fn some_async_fn() {}
+
+fn sync_side_effects() {}
+fn custom() -> impl Future<Output = ()> {
+    sync_side_effects();
+    async {}
+}
+
+fn do_something_to_future(future: &mut impl Future<Output = ()>) {}
+
+fn main() {
+    let _ = some_async_fn();
+    let _ = custom();
+
+    let mut future = some_async_fn();
+    do_something_to_future(&mut future);
+    let _ = future;
+}
diff --git a/src/tools/clippy/tests/ui/let_underscore_future.stderr b/src/tools/clippy/tests/ui/let_underscore_future.stderr
new file mode 100644
index 00000000000..33a748736a8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/let_underscore_future.stderr
@@ -0,0 +1,27 @@
+error: non-binding `let` on a future
+  --> $DIR/let_underscore_future.rs:14:5
+   |
+LL |     let _ = some_async_fn();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider awaiting the future or dropping explicitly with `std::mem::drop`
+   = note: `-D clippy::let-underscore-future` implied by `-D warnings`
+
+error: non-binding `let` on a future
+  --> $DIR/let_underscore_future.rs:15:5
+   |
+LL |     let _ = custom();
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider awaiting the future or dropping explicitly with `std::mem::drop`
+
+error: non-binding `let` on a future
+  --> $DIR/let_underscore_future.rs:19:5
+   |
+LL |     let _ = future;
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: consider awaiting the future or dropping explicitly with `std::mem::drop`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/let_underscore_lock.rs b/src/tools/clippy/tests/ui/let_underscore_lock.rs
index 7a7c4e92499..4dff4d766bc 100644
--- a/src/tools/clippy/tests/ui/let_underscore_lock.rs
+++ b/src/tools/clippy/tests/ui/let_underscore_lock.rs
@@ -3,20 +3,6 @@
 extern crate parking_lot;
 
 fn main() {
-    let m = std::sync::Mutex::new(());
-    let rw = std::sync::RwLock::new(());
-
-    let _ = m.lock();
-    let _ = rw.read();
-    let _ = rw.write();
-    let _ = m.try_lock();
-    let _ = rw.try_read();
-    let _ = rw.try_write();
-
-    // These shouldn't throw an error.
-    let _ = m;
-    let _ = rw;
-
     use parking_lot::{lock_api::RawMutex, Mutex, RwLock};
 
     let p_m: Mutex<()> = Mutex::const_new(RawMutex::INIT, ());
@@ -34,3 +20,20 @@ fn main() {
     let _ = p_m1;
     let _ = p_rw;
 }
+
+fn uplifted() {
+    // shouldn't lint std locks as they were uplifted as rustc's `let_underscore_lock`
+
+    let m = std::sync::Mutex::new(());
+    let rw = std::sync::RwLock::new(());
+
+    let _ = m.lock();
+    let _ = rw.read();
+    let _ = rw.write();
+    let _ = m.try_lock();
+    let _ = rw.try_read();
+    let _ = rw.try_write();
+
+    let _ = m;
+    let _ = rw;
+}
diff --git a/src/tools/clippy/tests/ui/let_underscore_lock.stderr b/src/tools/clippy/tests/ui/let_underscore_lock.stderr
index d7779e7b6c4..f137d411209 100644
--- a/src/tools/clippy/tests/ui/let_underscore_lock.stderr
+++ b/src/tools/clippy/tests/ui/let_underscore_lock.stderr
@@ -1,83 +1,35 @@
-error: non-binding let on a synchronization lock
+error: non-binding `let` on a synchronization lock
   --> $DIR/let_underscore_lock.rs:9:5
    |
-LL |     let _ = m.lock();
-   |     ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-   = note: `-D clippy::let-underscore-lock` implied by `-D warnings`
-
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:10:5
-   |
-LL |     let _ = rw.read();
-   |     ^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:11:5
-   |
-LL |     let _ = rw.write();
-   |     ^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:12:5
-   |
-LL |     let _ = m.try_lock();
-   |     ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:13:5
-   |
-LL |     let _ = rw.try_read();
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:14:5
-   |
-LL |     let _ = rw.try_write();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:23:5
-   |
 LL |     let _ = p_m.lock();
    |     ^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
+   = note: `-D clippy::let-underscore-lock` implied by `-D warnings`
 
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:26:5
+error: non-binding `let` on a synchronization lock
+  --> $DIR/let_underscore_lock.rs:12:5
    |
 LL |     let _ = p_m1.lock();
    |     ^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
 
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:29:5
+error: non-binding `let` on a synchronization lock
+  --> $DIR/let_underscore_lock.rs:15:5
    |
 LL |     let _ = p_rw.read();
    |     ^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
 
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:30:5
+error: non-binding `let` on a synchronization lock
+  --> $DIR/let_underscore_lock.rs:16:5
    |
 LL |     let _ = p_rw.write();
    |     ^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
 
-error: aborting due to 10 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/let_underscore_must_use.stderr b/src/tools/clippy/tests/ui/let_underscore_must_use.stderr
index bae60f2ff9b..28d760eb46e 100644
--- a/src/tools/clippy/tests/ui/let_underscore_must_use.stderr
+++ b/src/tools/clippy/tests/ui/let_underscore_must_use.stderr
@@ -1,4 +1,4 @@
-error: non-binding let on a result of a `#[must_use]` function
+error: non-binding `let` on a result of a `#[must_use]` function
   --> $DIR/let_underscore_must_use.rs:67:5
    |
 LL |     let _ = f();
@@ -7,7 +7,7 @@ LL |     let _ = f();
    = help: consider explicitly using function result
    = note: `-D clippy::let-underscore-must-use` implied by `-D warnings`
 
-error: non-binding let on an expression with `#[must_use]` type
+error: non-binding `let` on an expression with `#[must_use]` type
   --> $DIR/let_underscore_must_use.rs:68:5
    |
 LL |     let _ = g();
@@ -15,7 +15,7 @@ LL |     let _ = g();
    |
    = help: consider explicitly using expression value
 
-error: non-binding let on a result of a `#[must_use]` function
+error: non-binding `let` on a result of a `#[must_use]` function
   --> $DIR/let_underscore_must_use.rs:70:5
    |
 LL |     let _ = l(0_u32);
@@ -23,7 +23,7 @@ LL |     let _ = l(0_u32);
    |
    = help: consider explicitly using function result
 
-error: non-binding let on a result of a `#[must_use]` function
+error: non-binding `let` on a result of a `#[must_use]` function
   --> $DIR/let_underscore_must_use.rs:74:5
    |
 LL |     let _ = s.f();
@@ -31,7 +31,7 @@ LL |     let _ = s.f();
    |
    = help: consider explicitly using function result
 
-error: non-binding let on an expression with `#[must_use]` type
+error: non-binding `let` on an expression with `#[must_use]` type
   --> $DIR/let_underscore_must_use.rs:75:5
    |
 LL |     let _ = s.g();
@@ -39,7 +39,7 @@ LL |     let _ = s.g();
    |
    = help: consider explicitly using expression value
 
-error: non-binding let on a result of a `#[must_use]` function
+error: non-binding `let` on a result of a `#[must_use]` function
   --> $DIR/let_underscore_must_use.rs:78:5
    |
 LL |     let _ = S::h();
@@ -47,7 +47,7 @@ LL |     let _ = S::h();
    |
    = help: consider explicitly using function result
 
-error: non-binding let on an expression with `#[must_use]` type
+error: non-binding `let` on an expression with `#[must_use]` type
   --> $DIR/let_underscore_must_use.rs:79:5
    |
 LL |     let _ = S::p();
@@ -55,7 +55,7 @@ LL |     let _ = S::p();
    |
    = help: consider explicitly using expression value
 
-error: non-binding let on a result of a `#[must_use]` function
+error: non-binding `let` on a result of a `#[must_use]` function
   --> $DIR/let_underscore_must_use.rs:81:5
    |
 LL |     let _ = S::a();
@@ -63,7 +63,7 @@ LL |     let _ = S::a();
    |
    = help: consider explicitly using function result
 
-error: non-binding let on an expression with `#[must_use]` type
+error: non-binding `let` on an expression with `#[must_use]` type
   --> $DIR/let_underscore_must_use.rs:83:5
    |
 LL |     let _ = if true { Ok(()) } else { Err(()) };
@@ -71,7 +71,7 @@ LL |     let _ = if true { Ok(()) } else { Err(()) };
    |
    = help: consider explicitly using expression value
 
-error: non-binding let on a result of a `#[must_use]` function
+error: non-binding `let` on a result of a `#[must_use]` function
   --> $DIR/let_underscore_must_use.rs:87:5
    |
 LL |     let _ = a.is_ok();
@@ -79,7 +79,7 @@ LL |     let _ = a.is_ok();
    |
    = help: consider explicitly using function result
 
-error: non-binding let on an expression with `#[must_use]` type
+error: non-binding `let` on an expression with `#[must_use]` type
   --> $DIR/let_underscore_must_use.rs:89:5
    |
 LL |     let _ = a.map(|_| ());
@@ -87,7 +87,7 @@ LL |     let _ = a.map(|_| ());
    |
    = help: consider explicitly using expression value
 
-error: non-binding let on an expression with `#[must_use]` type
+error: non-binding `let` on an expression with `#[must_use]` type
   --> $DIR/let_underscore_must_use.rs:91:5
    |
 LL |     let _ = a;
diff --git a/src/tools/clippy/tests/ui/manual_flatten.rs b/src/tools/clippy/tests/ui/manual_flatten.rs
index 96cd87c0e19..552213a7ff2 100644
--- a/src/tools/clippy/tests/ui/manual_flatten.rs
+++ b/src/tools/clippy/tests/ui/manual_flatten.rs
@@ -10,7 +10,7 @@ fn main() {
         }
     }
 
-    // Test for loop over implicitly implicitly adjusted `Iterator` with `if let` statement
+    // Test for loop over implicitly adjusted `Iterator` with `if let` statement
     let y: Vec<Result<i32, i32>> = vec![];
     for n in y.clone() {
         if let Ok(n) = n {
diff --git a/src/tools/clippy/tests/ui/manual_instant_elapsed.fixed b/src/tools/clippy/tests/ui/manual_instant_elapsed.fixed
index 0fa776b7b2e..85a91543c89 100644
--- a/src/tools/clippy/tests/ui/manual_instant_elapsed.fixed
+++ b/src/tools/clippy/tests/ui/manual_instant_elapsed.fixed
@@ -1,6 +1,7 @@
 // run-rustfix
 #![warn(clippy::manual_instant_elapsed)]
 #![allow(clippy::unnecessary_operation)]
+#![allow(clippy::unchecked_duration_subtraction)]
 #![allow(unused_variables)]
 #![allow(unused_must_use)]
 
diff --git a/src/tools/clippy/tests/ui/manual_instant_elapsed.rs b/src/tools/clippy/tests/ui/manual_instant_elapsed.rs
index 5b11b84535d..c98cb15b916 100644
--- a/src/tools/clippy/tests/ui/manual_instant_elapsed.rs
+++ b/src/tools/clippy/tests/ui/manual_instant_elapsed.rs
@@ -1,6 +1,7 @@
 // run-rustfix
 #![warn(clippy::manual_instant_elapsed)]
 #![allow(clippy::unnecessary_operation)]
+#![allow(clippy::unchecked_duration_subtraction)]
 #![allow(unused_variables)]
 #![allow(unused_must_use)]
 
diff --git a/src/tools/clippy/tests/ui/manual_instant_elapsed.stderr b/src/tools/clippy/tests/ui/manual_instant_elapsed.stderr
index 5537f5642a2..4ce1f689107 100644
--- a/src/tools/clippy/tests/ui/manual_instant_elapsed.stderr
+++ b/src/tools/clippy/tests/ui/manual_instant_elapsed.stderr
@@ -1,5 +1,5 @@
 error: manual implementation of `Instant::elapsed`
-  --> $DIR/manual_instant_elapsed.rs:17:20
+  --> $DIR/manual_instant_elapsed.rs:18:20
    |
 LL |     let duration = Instant::now() - prev_instant;
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `prev_instant.elapsed()`
@@ -7,7 +7,7 @@ LL |     let duration = Instant::now() - prev_instant;
    = note: `-D clippy::manual-instant-elapsed` implied by `-D warnings`
 
 error: manual implementation of `Instant::elapsed`
-  --> $DIR/manual_instant_elapsed.rs:26:5
+  --> $DIR/manual_instant_elapsed.rs:27:5
    |
 LL |     Instant::now() - *ref_to_instant; // to ensure parens are added correctly
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*ref_to_instant).elapsed()`
diff --git a/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed b/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed
new file mode 100644
index 00000000000..765bb785994
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed
@@ -0,0 +1,45 @@
+// run-rustfix
+
+#![feature(custom_inner_attributes)]
+#![allow(unused, dead_code)]
+#![warn(clippy::manual_is_ascii_check)]
+
+fn main() {
+    assert!('x'.is_ascii_lowercase());
+    assert!('X'.is_ascii_uppercase());
+    assert!(b'x'.is_ascii_lowercase());
+    assert!(b'X'.is_ascii_uppercase());
+
+    let num = '2';
+    assert!(num.is_ascii_digit());
+    assert!(b'1'.is_ascii_digit());
+    assert!('x'.is_ascii_alphabetic());
+
+    assert!(matches!('x', 'A'..='Z' | 'a'..='z' | '_'));
+}
+
+fn msrv_1_23() {
+    #![clippy::msrv = "1.23"]
+
+    assert!(matches!(b'1', b'0'..=b'9'));
+    assert!(matches!('X', 'A'..='Z'));
+    assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+}
+
+fn msrv_1_24() {
+    #![clippy::msrv = "1.24"]
+
+    assert!(b'1'.is_ascii_digit());
+    assert!('X'.is_ascii_uppercase());
+    assert!('x'.is_ascii_alphabetic());
+}
+
+fn msrv_1_46() {
+    #![clippy::msrv = "1.46"]
+    const FOO: bool = matches!('x', '0'..='9');
+}
+
+fn msrv_1_47() {
+    #![clippy::msrv = "1.47"]
+    const FOO: bool = 'x'.is_ascii_digit();
+}
diff --git a/src/tools/clippy/tests/ui/manual_is_ascii_check.rs b/src/tools/clippy/tests/ui/manual_is_ascii_check.rs
new file mode 100644
index 00000000000..be133161041
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_is_ascii_check.rs
@@ -0,0 +1,45 @@
+// run-rustfix
+
+#![feature(custom_inner_attributes)]
+#![allow(unused, dead_code)]
+#![warn(clippy::manual_is_ascii_check)]
+
+fn main() {
+    assert!(matches!('x', 'a'..='z'));
+    assert!(matches!('X', 'A'..='Z'));
+    assert!(matches!(b'x', b'a'..=b'z'));
+    assert!(matches!(b'X', b'A'..=b'Z'));
+
+    let num = '2';
+    assert!(matches!(num, '0'..='9'));
+    assert!(matches!(b'1', b'0'..=b'9'));
+    assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+
+    assert!(matches!('x', 'A'..='Z' | 'a'..='z' | '_'));
+}
+
+fn msrv_1_23() {
+    #![clippy::msrv = "1.23"]
+
+    assert!(matches!(b'1', b'0'..=b'9'));
+    assert!(matches!('X', 'A'..='Z'));
+    assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+}
+
+fn msrv_1_24() {
+    #![clippy::msrv = "1.24"]
+
+    assert!(matches!(b'1', b'0'..=b'9'));
+    assert!(matches!('X', 'A'..='Z'));
+    assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+}
+
+fn msrv_1_46() {
+    #![clippy::msrv = "1.46"]
+    const FOO: bool = matches!('x', '0'..='9');
+}
+
+fn msrv_1_47() {
+    #![clippy::msrv = "1.47"]
+    const FOO: bool = matches!('x', '0'..='9');
+}
diff --git a/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr b/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr
new file mode 100644
index 00000000000..c0a9d4db1a1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr
@@ -0,0 +1,70 @@
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:8:13
+   |
+LL |     assert!(matches!('x', 'a'..='z'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_lowercase()`
+   |
+   = note: `-D clippy::manual-is-ascii-check` implied by `-D warnings`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:9:13
+   |
+LL |     assert!(matches!('X', 'A'..='Z'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:10:13
+   |
+LL |     assert!(matches!(b'x', b'a'..=b'z'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'x'.is_ascii_lowercase()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:11:13
+   |
+LL |     assert!(matches!(b'X', b'A'..=b'Z'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'X'.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:14:13
+   |
+LL |     assert!(matches!(num, '0'..='9'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.is_ascii_digit()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:15:13
+   |
+LL |     assert!(matches!(b'1', b'0'..=b'9'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:16:13
+   |
+LL |     assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:32:13
+   |
+LL |     assert!(matches!(b'1', b'0'..=b'9'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:33:13
+   |
+LL |     assert!(matches!('X', 'A'..='Z'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:34:13
+   |
+LL |     assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:44:23
+   |
+LL |     const FOO: bool = matches!('x', '0'..='9');
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_digit()`
+
+error: aborting due to 11 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_let_else.rs b/src/tools/clippy/tests/ui/manual_let_else.rs
new file mode 100644
index 00000000000..2ef40e5911a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_let_else.rs
@@ -0,0 +1,237 @@
+#![allow(unused_braces, unused_variables, dead_code)]
+#![allow(
+    clippy::collapsible_else_if,
+    clippy::unused_unit,
+    clippy::let_unit_value,
+    clippy::match_single_binding,
+    clippy::never_loop
+)]
+#![warn(clippy::manual_let_else)]
+
+fn g() -> Option<()> {
+    None
+}
+
+fn main() {}
+
+fn fire() {
+    let v = if let Some(v_some) = g() { v_some } else { return };
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        return;
+    };
+
+    let v = if let Some(v) = g() {
+        // Blocks around the identity should have no impact
+        {
+            { v }
+        }
+    } else {
+        // Some computation should still make it fire
+        g();
+        return;
+    };
+
+    // continue and break diverge
+    loop {
+        let v = if let Some(v_some) = g() { v_some } else { continue };
+        let v = if let Some(v_some) = g() { v_some } else { break };
+    }
+
+    // panic also diverges
+    let v = if let Some(v_some) = g() { v_some } else { panic!() };
+
+    // abort also diverges
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        std::process::abort()
+    };
+
+    // If whose two branches diverge also diverges
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        if true { return } else { panic!() }
+    };
+
+    // Diverging after an if still makes the block diverge:
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        if true {}
+        panic!();
+    };
+
+    // A match diverges if all branches diverge:
+    // Note: the corresponding let-else requires a ; at the end of the match
+    // as otherwise the type checker does not turn it into a ! type.
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        match () {
+            _ if panic!() => {},
+            _ => panic!(),
+        }
+    };
+
+    // An if's expression can cause divergence:
+    let v = if let Some(v_some) = g() { v_some } else { if panic!() {} };
+
+    // An expression of a match can cause divergence:
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        match panic!() {
+            _ => {},
+        }
+    };
+
+    // Top level else if
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else if true {
+        return;
+    } else {
+        panic!("diverge");
+    };
+
+    // All match arms diverge
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        match (g(), g()) {
+            (Some(_), None) => return,
+            (None, Some(_)) => {
+                if true {
+                    return;
+                } else {
+                    panic!();
+                }
+            },
+            _ => return,
+        }
+    };
+
+    // Tuples supported for the declared variables
+    let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
+        v_some
+    } else {
+        return;
+    };
+
+    // Tuples supported for the identity block and pattern
+    let v = if let (Some(v_some), w_some) = (g(), 0) {
+        (w_some, v_some)
+    } else {
+        return;
+    };
+
+    // entirely inside macro lints
+    macro_rules! create_binding_if_some {
+        ($n:ident, $e:expr) => {
+            let $n = if let Some(v) = $e { v } else { return };
+        };
+    }
+    create_binding_if_some!(w, g());
+}
+
+fn not_fire() {
+    let v = if let Some(v_some) = g() {
+        // Nothing returned. Should not fire.
+    } else {
+        return;
+    };
+
+    let w = 0;
+    let v = if let Some(v_some) = g() {
+        // Different variable than v_some. Should not fire.
+        w
+    } else {
+        return;
+    };
+
+    let v = if let Some(v_some) = g() {
+        // Computation in then clause. Should not fire.
+        g();
+        v_some
+    } else {
+        return;
+    };
+
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        if false {
+            return;
+        }
+        // This doesn't diverge. Should not fire.
+        ()
+    };
+
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        // There is one match arm that doesn't diverge. Should not fire.
+        match (g(), g()) {
+            (Some(_), None) => return,
+            (None, Some(_)) => return,
+            (Some(_), Some(_)) => (),
+            _ => return,
+        }
+    };
+
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        // loop with a break statement inside does not diverge.
+        loop {
+            break;
+        }
+    };
+
+    enum Uninhabited {}
+    fn un() -> Uninhabited {
+        panic!()
+    }
+    let v = if let Some(v_some) = None {
+        v_some
+    } else {
+        // Don't lint if the type is uninhabited but not !
+        un()
+    };
+
+    fn question_mark() -> Option<()> {
+        let v = if let Some(v) = g() {
+            v
+        } else {
+            // Question mark does not diverge
+            g()?
+        };
+        Some(v)
+    }
+
+    // Macro boundary inside let
+    macro_rules! some_or_return {
+        ($e:expr) => {
+            if let Some(v) = $e { v } else { return }
+        };
+    }
+    let v = some_or_return!(g());
+
+    // Also macro boundary inside let, but inside a macro
+    macro_rules! create_binding_if_some_nf {
+        ($n:ident, $e:expr) => {
+            let $n = some_or_return!($e);
+        };
+    }
+    create_binding_if_some_nf!(v, g());
+
+    // Already a let-else
+    let Some(a) = (if let Some(b) = Some(Some(())) { b } else { return }) else { panic!() };
+
+    // If a type annotation is present, don't lint as
+    // expressing the type might be too hard
+    let v: () = if let Some(v_some) = g() { v_some } else { panic!() };
+}
diff --git a/src/tools/clippy/tests/ui/manual_let_else.stderr b/src/tools/clippy/tests/ui/manual_let_else.stderr
new file mode 100644
index 00000000000..453b68b8bd0
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_let_else.stderr
@@ -0,0 +1,263 @@
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:18:5
+   |
+LL |     let v = if let Some(v_some) = g() { v_some } else { return };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = 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
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else {
+LL | |         return;
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else {
+LL +         return;
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:25:5
+   |
+LL | /     let v = if let Some(v) = g() {
+LL | |         // Blocks around the identity should have no impact
+LL | |         {
+LL | |             { v }
+...  |
+LL | |         return;
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v) = g() else {
+LL +         // Some computation should still make it fire
+LL +         g();
+LL +         return;
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:38:9
+   |
+LL |         let v = if let Some(v_some) = g() { v_some } else { continue };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { continue };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:39:9
+   |
+LL |         let v = if let Some(v_some) = g() { v_some } else { break };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { break };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:43:5
+   |
+LL |     let v = if let Some(v_some) = g() { v_some } else { panic!() };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { panic!() };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:46:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else {
+LL | |         std::process::abort()
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else {
+LL +         std::process::abort()
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:53:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else {
+LL | |         if true { return } else { panic!() }
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else {
+LL +         if true { return } else { panic!() }
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:60:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else {
+LL | |         if true {}
+LL | |         panic!();
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else {
+LL +         if true {}
+LL +         panic!();
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:70:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else {
+LL | |         match () {
+...  |
+LL | |         }
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else {
+LL +         match () {
+LL +             _ if panic!() => {},
+LL +             _ => panic!(),
+LL +         }
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:80: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!() {} };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:83:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else {
+LL | |         match panic!() {
+LL | |             _ => {},
+LL | |         }
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else {
+LL +         match panic!() {
+LL +             _ => {},
+LL +         }
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:92:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else if true {
+LL | |         return;
+LL | |     } else {
+LL | |         panic!("diverge");
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else { if true {
+LL +         return;
+LL +     } else {
+LL +         panic!("diverge");
+LL +     } };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:101:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else {
+LL | |         match (g(), g()) {
+...  |
+LL | |         }
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else {
+LL +         match (g(), g()) {
+LL +             (Some(_), None) => return,
+LL +             (None, Some(_)) => {
+LL +                 if true {
+LL +                     return;
+LL +                 } else {
+LL +                     panic!();
+LL +                 }
+LL +             },
+LL +             _ => return,
+LL +         }
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:118:5
+   |
+LL | /     let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
+LL | |         v_some
+LL | |     } else {
+LL | |         return;
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g().map(|v| (v, 42)) else {
+LL +         return;
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:125:5
+   |
+LL | /     let v = if let (Some(v_some), w_some) = (g(), 0) {
+LL | |         (w_some, v_some)
+LL | |     } else {
+LL | |         return;
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let (Some(v_some), w_some) = (g(), 0) else {
+LL +         return;
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:134:13
+   |
+LL |             let $n = if let Some(v) = $e { v } else { return };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
+...
+LL |     create_binding_if_some!(w, g());
+   |     ------------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 17 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.rs b/src/tools/clippy/tests/ui/manual_let_else_match.rs
new file mode 100644
index 00000000000..93c86ca24fe
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.rs
@@ -0,0 +1,121 @@
+#![allow(unused_braces, unused_variables, dead_code)]
+#![allow(clippy::collapsible_else_if, clippy::let_unit_value)]
+#![warn(clippy::manual_let_else)]
+// Ensure that we don't conflict with match -> if let lints
+#![warn(clippy::single_match_else, clippy::single_match)]
+
+fn f() -> Result<u32, u32> {
+    Ok(0)
+}
+
+fn g() -> Option<()> {
+    None
+}
+
+fn h() -> (Option<()>, Option<()>) {
+    (None, None)
+}
+
+enum Variant {
+    Foo,
+    Bar(u32),
+    Baz(u32),
+}
+
+fn build_enum() -> Variant {
+    Variant::Foo
+}
+
+fn main() {}
+
+fn fire() {
+    let v = match g() {
+        Some(v_some) => v_some,
+        None => return,
+    };
+
+    let v = match g() {
+        Some(v_some) => v_some,
+        _ => return,
+    };
+
+    loop {
+        // More complex pattern for the identity arm and diverging arm
+        let v = match h() {
+            (Some(_), Some(_)) | (None, None) => continue,
+            (Some(v), None) | (None, Some(v)) => v,
+        };
+        // Custom enums are supported as long as the "else" arm is a simple _
+        let v = match build_enum() {
+            _ => continue,
+            Variant::Bar(v) | Variant::Baz(v) => v,
+        };
+    }
+
+    // There is a _ in the diverging arm
+    // TODO also support unused bindings aka _v
+    let v = match f() {
+        Ok(v) => v,
+        Err(_) => return,
+    };
+
+    // Err(()) is an allowed pattern
+    let v = match f().map_err(|_| ()) {
+        Ok(v) => v,
+        Err(()) => return,
+    };
+}
+
+fn not_fire() {
+    // Multiple diverging arms
+    let v = match h() {
+        _ => panic!(),
+        (None, Some(_v)) => return,
+        (Some(v), None) => v,
+    };
+
+    // Multiple identity arms
+    let v = match h() {
+        _ => panic!(),
+        (None, Some(v)) => v,
+        (Some(v), None) => v,
+    };
+
+    // No diverging arm at all, only identity arms.
+    // This is no case for let else, but destructuring assignment.
+    let v = match f() {
+        Ok(v) => v,
+        Err(e) => e,
+    };
+
+    // The identity arm has a guard
+    let v = match g() {
+        Some(v) if g().is_none() => v,
+        _ => return,
+    };
+
+    // The diverging arm has a guard
+    let v = match f() {
+        Err(v) if v > 0 => panic!(),
+        Ok(v) | Err(v) => v,
+    };
+
+    // The diverging arm creates a binding
+    let v = match f() {
+        Ok(v) => v,
+        Err(e) => panic!("error: {e}"),
+    };
+
+    // Custom enum where the diverging arm
+    // explicitly mentions the variant
+    let v = match build_enum() {
+        Variant::Foo => return,
+        Variant::Bar(v) | Variant::Baz(v) => v,
+    };
+
+    // The custom enum is surrounded by an Err()
+    let v = match Err(build_enum()) {
+        Ok(v) | Err(Variant::Bar(v) | Variant::Baz(v)) => v,
+        Err(Variant::Foo) => return,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.stderr b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
new file mode 100644
index 00000000000..38be5ac5454
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
@@ -0,0 +1,58 @@
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:32:5
+   |
+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 };`
+   |
+   = note: `-D clippy::manual-let-else` implied by `-D warnings`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:37:5
+   |
+LL | /     let v = match g() {
+LL | |         Some(v_some) => v_some,
+LL | |         _ => return,
+LL | |     };
+   | |______^ help: consider writing: `let Some(v_some) = g() else { return };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:44:9
+   |
+LL | /         let v = match h() {
+LL | |             (Some(_), Some(_)) | (None, None) => continue,
+LL | |             (Some(v), None) | (None, Some(v)) => v,
+LL | |         };
+   | |__________^ help: consider writing: `let (Some(v), None) | (None, Some(v)) = h() else { continue };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:49:9
+   |
+LL | /         let v = match build_enum() {
+LL | |             _ => continue,
+LL | |             Variant::Bar(v) | Variant::Baz(v) => v,
+LL | |         };
+   | |__________^ help: consider writing: `let Variant::Bar(v) | Variant::Baz(v) = build_enum() else { continue };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:57:5
+   |
+LL | /     let v = match f() {
+LL | |         Ok(v) => v,
+LL | |         Err(_) => return,
+LL | |     };
+   | |______^ help: consider writing: `let Ok(v) = f() else { return };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:63:5
+   |
+LL | /     let v = match f().map_err(|_| ()) {
+LL | |         Ok(v) => v,
+LL | |         Err(()) => return,
+LL | |     };
+   | |______^ help: consider writing: `let Ok(v) = f().map_err(|_| ()) else { return };`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_ok_or.fixed b/src/tools/clippy/tests/ui/manual_ok_or.fixed
index d864f855453..fc8511626b3 100644
--- a/src/tools/clippy/tests/ui/manual_ok_or.fixed
+++ b/src/tools/clippy/tests/ui/manual_ok_or.fixed
@@ -1,5 +1,6 @@
 // run-rustfix
 #![warn(clippy::manual_ok_or)]
+#![allow(clippy::or_fun_call)]
 #![allow(clippy::disallowed_names)]
 #![allow(clippy::redundant_closure)]
 #![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/manual_ok_or.rs b/src/tools/clippy/tests/ui/manual_ok_or.rs
index 6264768460e..b5303d33f5f 100644
--- a/src/tools/clippy/tests/ui/manual_ok_or.rs
+++ b/src/tools/clippy/tests/ui/manual_ok_or.rs
@@ -1,5 +1,6 @@
 // run-rustfix
 #![warn(clippy::manual_ok_or)]
+#![allow(clippy::or_fun_call)]
 #![allow(clippy::disallowed_names)]
 #![allow(clippy::redundant_closure)]
 #![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/manual_ok_or.stderr b/src/tools/clippy/tests/ui/manual_ok_or.stderr
index 65459a09738..b4a17f143e3 100644
--- a/src/tools/clippy/tests/ui/manual_ok_or.stderr
+++ b/src/tools/clippy/tests/ui/manual_ok_or.stderr
@@ -1,5 +1,5 @@
 error: this pattern reimplements `Option::ok_or`
-  --> $DIR/manual_ok_or.rs:11:5
+  --> $DIR/manual_ok_or.rs:12:5
    |
 LL |     foo.map_or(Err("error"), |v| Ok(v));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `foo.ok_or("error")`
@@ -7,19 +7,19 @@ LL |     foo.map_or(Err("error"), |v| Ok(v));
    = note: `-D clippy::manual-ok-or` implied by `-D warnings`
 
 error: this pattern reimplements `Option::ok_or`
-  --> $DIR/manual_ok_or.rs:14:5
+  --> $DIR/manual_ok_or.rs:15:5
    |
 LL |     foo.map_or(Err("error"), Ok);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `foo.ok_or("error")`
 
 error: this pattern reimplements `Option::ok_or`
-  --> $DIR/manual_ok_or.rs:17:5
+  --> $DIR/manual_ok_or.rs:18:5
    |
 LL |     None::<i32>.map_or(Err("error"), |v| Ok(v));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `None::<i32>.ok_or("error")`
 
 error: this pattern reimplements `Option::ok_or`
-  --> $DIR/manual_ok_or.rs:21:5
+  --> $DIR/manual_ok_or.rs:22:5
    |
 LL | /     foo.map_or(Err::<i32, &str>(
 LL | |         &format!(
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
index 312819a0a2c..53628ef6531 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
@@ -1,7 +1,6 @@
 // run-rustfix
 
 #![warn(clippy::all, clippy::pedantic)]
-#![allow(clippy::let_underscore_drop)]
 #![allow(clippy::missing_docs_in_private_items)]
 #![allow(clippy::map_identity)]
 #![allow(clippy::redundant_closure)]
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.rs b/src/tools/clippy/tests/ui/map_flatten_fixable.rs
index 3fbf4f9a1b0..76016c8ed3c 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.rs
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.rs
@@ -1,7 +1,6 @@
 // run-rustfix
 
 #![warn(clippy::all, clippy::pedantic)]
-#![allow(clippy::let_underscore_drop)]
 #![allow(clippy::missing_docs_in_private_items)]
 #![allow(clippy::map_identity)]
 #![allow(clippy::redundant_closure)]
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
index c91f0b9ae94..b6b0c4d09c3 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
@@ -1,5 +1,5 @@
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:18:47
+  --> $DIR/map_flatten_fixable.rs:17:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id)`
@@ -7,43 +7,43 @@ LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().coll
    = note: `-D clippy::map-flatten` implied by `-D warnings`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:19:47
+  --> $DIR/map_flatten_fixable.rs:18:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_ref)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:20:47
+  --> $DIR/map_flatten_fixable.rs:19:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_closure)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:21:47
+  --> $DIR/map_flatten_fixable.rs:20:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|x| x.checked_add(1))`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:24:47
+  --> $DIR/map_flatten_fixable.rs:23:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|x| 0..x)`
 
 error: called `map(..).flatten()` on `Option`
-  --> $DIR/map_flatten_fixable.rs:27:40
+  --> $DIR/map_flatten_fixable.rs:26:40
    |
 LL |     let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
    |                                        ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
 
 error: called `map(..).flatten()` on `Result`
-  --> $DIR/map_flatten_fixable.rs:30:42
+  --> $DIR/map_flatten_fixable.rs:29:42
    |
 LL |     let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten();
    |                                          ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:39:10
+  --> $DIR/map_flatten_fixable.rs:38:10
    |
 LL |           .map(|n| match n {
    |  __________^
@@ -72,7 +72,7 @@ LL ~         });
    |
 
 error: called `map(..).flatten()` on `Option`
-  --> $DIR/map_flatten_fixable.rs:59:10
+  --> $DIR/map_flatten_fixable.rs:58:10
    |
 LL |           .map(|_| {
    |  __________^
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 2498007694c..968f462f8a0 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
@@ -2,7 +2,12 @@
 
 #![feature(custom_inner_attributes)]
 #![warn(clippy::match_like_matches_macro)]
-#![allow(unreachable_patterns, dead_code, clippy::equatable_if_let)]
+#![allow(
+    unreachable_patterns,
+    dead_code,
+    clippy::equatable_if_let,
+    clippy::needless_borrowed_reference
+)]
 
 fn main() {
     let x = Some(5);
diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs
index b4e48499bd0..c6b479e27c5 100644
--- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs
+++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs
@@ -2,7 +2,12 @@
 
 #![feature(custom_inner_attributes)]
 #![warn(clippy::match_like_matches_macro)]
-#![allow(unreachable_patterns, dead_code, clippy::equatable_if_let)]
+#![allow(
+    unreachable_patterns,
+    dead_code,
+    clippy::equatable_if_let,
+    clippy::needless_borrowed_reference
+)]
 
 fn main() {
     let x = Some(5);
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 f1d1c23aeb0..a4df8008ac2 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
@@ -1,5 +1,5 @@
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:11:14
+  --> $DIR/match_expr_like_matches_macro.rs:16:14
    |
 LL |       let _y = match x {
    |  ______________^
@@ -11,7 +11,7 @@ LL | |     };
    = note: `-D clippy::match-like-matches-macro` implied by `-D warnings`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:17:14
+  --> $DIR/match_expr_like_matches_macro.rs:22:14
    |
 LL |       let _w = match x {
    |  ______________^
@@ -21,7 +21,7 @@ LL | |     };
    | |_____^ help: try this: `matches!(x, Some(_))`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/match_expr_like_matches_macro.rs:23:14
+  --> $DIR/match_expr_like_matches_macro.rs:28:14
    |
 LL |       let _z = match x {
    |  ______________^
@@ -33,7 +33,7 @@ LL | |     };
    = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:29:15
+  --> $DIR/match_expr_like_matches_macro.rs:34:15
    |
 LL |       let _zz = match x {
    |  _______________^
@@ -43,13 +43,13 @@ LL | |     };
    | |_____^ help: try this: `!matches!(x, Some(r) if r == 0)`
 
 error: if let .. else expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:35:16
+  --> $DIR/match_expr_like_matches_macro.rs:40:16
    |
 LL |     let _zzz = if let Some(5) = x { true } else { false };
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `matches!(x, Some(5))`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:59:20
+  --> $DIR/match_expr_like_matches_macro.rs:64:20
    |
 LL |           let _ans = match x {
    |  ____________________^
@@ -60,7 +60,7 @@ LL | |         };
    | |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:69:20
+  --> $DIR/match_expr_like_matches_macro.rs:74:20
    |
 LL |           let _ans = match x {
    |  ____________________^
@@ -73,7 +73,7 @@ LL | |         };
    | |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:79:20
+  --> $DIR/match_expr_like_matches_macro.rs:84:20
    |
 LL |           let _ans = match x {
    |  ____________________^
@@ -84,7 +84,7 @@ LL | |         };
    | |_________^ help: try this: `!matches!(x, E::B(_) | E::C)`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:139:18
+  --> $DIR/match_expr_like_matches_macro.rs:144:18
    |
 LL |           let _z = match &z {
    |  __________________^
@@ -94,7 +94,7 @@ LL | |         };
    | |_________^ help: try this: `matches!(z, Some(3))`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:148:18
+  --> $DIR/match_expr_like_matches_macro.rs:153:18
    |
 LL |           let _z = match &z {
    |  __________________^
@@ -104,7 +104,7 @@ LL | |         };
    | |_________^ help: try this: `matches!(&z, Some(3))`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:165:21
+  --> $DIR/match_expr_like_matches_macro.rs:170:21
    |
 LL |               let _ = match &z {
    |  _____________________^
@@ -114,7 +114,7 @@ LL | |             };
    | |_____________^ help: try this: `matches!(&z, AnEnum::X)`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:179:20
+  --> $DIR/match_expr_like_matches_macro.rs:184:20
    |
 LL |           let _res = match &val {
    |  ____________________^
@@ -124,7 +124,7 @@ LL | |         };
    | |_________^ help: try this: `matches!(&val, &Some(ref _a))`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:191:20
+  --> $DIR/match_expr_like_matches_macro.rs:196:20
    |
 LL |           let _res = match &val {
    |  ____________________^
@@ -134,7 +134,7 @@ LL | |         };
    | |_________^ help: try this: `matches!(&val, &Some(ref _a))`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:251:14
+  --> $DIR/match_expr_like_matches_macro.rs:256:14
    |
 LL |       let _y = match Some(5) {
    |  ______________^
diff --git a/src/tools/clippy/tests/ui/missing_panics_doc.stderr b/src/tools/clippy/tests/ui/missing_panics_doc.stderr
index c9ded7f1ad0..183c262ce0b 100644
--- a/src/tools/clippy/tests/ui/missing_panics_doc.stderr
+++ b/src/tools/clippy/tests/ui/missing_panics_doc.stderr
@@ -1,11 +1,8 @@
 error: docs for function which may panic missing `# Panics` section
   --> $DIR/missing_panics_doc.rs:6:1
    |
-LL | / pub fn unwrap() {
-LL | |     let result = Err("Hi");
-LL | |     result.unwrap()
-LL | | }
-   | |_^
+LL | pub fn unwrap() {
+   | ^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
   --> $DIR/missing_panics_doc.rs:8:5
@@ -17,10 +14,8 @@ LL |     result.unwrap()
 error: docs for function which may panic missing `# Panics` section
   --> $DIR/missing_panics_doc.rs:12:1
    |
-LL | / pub fn panic() {
-LL | |     panic!("This function panics")
-LL | | }
-   | |_^
+LL | pub fn panic() {
+   | ^^^^^^^^^^^^^^
    |
 note: first possible panic found here
   --> $DIR/missing_panics_doc.rs:13:5
@@ -31,10 +26,8 @@ LL |     panic!("This function panics")
 error: docs for function which may panic missing `# Panics` section
   --> $DIR/missing_panics_doc.rs:17:1
    |
-LL | / pub fn todo() {
-LL | |     todo!()
-LL | | }
-   | |_^
+LL | pub fn todo() {
+   | ^^^^^^^^^^^^^
    |
 note: first possible panic found here
   --> $DIR/missing_panics_doc.rs:18:5
@@ -45,14 +38,8 @@ LL |     todo!()
 error: docs for function which may panic missing `# Panics` section
   --> $DIR/missing_panics_doc.rs:22:1
    |
-LL | / pub fn inner_body(opt: Option<u32>) {
-LL | |     opt.map(|x| {
-LL | |         if x == 10 {
-LL | |             panic!()
-LL | |         }
-LL | |     });
-LL | | }
-   | |_^
+LL | pub fn inner_body(opt: Option<u32>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
   --> $DIR/missing_panics_doc.rs:25:13
@@ -63,10 +50,8 @@ LL |             panic!()
 error: docs for function which may panic missing `# Panics` section
   --> $DIR/missing_panics_doc.rs:31:1
    |
-LL | / pub fn unreachable_and_panic() {
-LL | |     if true { unreachable!() } else { panic!() }
-LL | | }
-   | |_^
+LL | pub fn unreachable_and_panic() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
   --> $DIR/missing_panics_doc.rs:32:39
@@ -77,11 +62,8 @@ LL |     if true { unreachable!() } else { panic!() }
 error: docs for function which may panic missing `# Panics` section
   --> $DIR/missing_panics_doc.rs:36:1
    |
-LL | / pub fn assert_eq() {
-LL | |     let x = 0;
-LL | |     assert_eq!(x, 0);
-LL | | }
-   | |_^
+LL | pub fn assert_eq() {
+   | ^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
   --> $DIR/missing_panics_doc.rs:38:5
@@ -92,11 +74,8 @@ LL |     assert_eq!(x, 0);
 error: docs for function which may panic missing `# Panics` section
   --> $DIR/missing_panics_doc.rs:42:1
    |
-LL | / pub fn assert_ne() {
-LL | |     let x = 0;
-LL | |     assert_ne!(x, 0);
-LL | | }
-   | |_^
+LL | pub fn assert_ne() {
+   | ^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
   --> $DIR/missing_panics_doc.rs:44:5
diff --git a/src/tools/clippy/tests/ui/mut_from_ref.rs b/src/tools/clippy/tests/ui/mut_from_ref.rs
index 370dbd58821..7de15330594 100644
--- a/src/tools/clippy/tests/ui/mut_from_ref.rs
+++ b/src/tools/clippy/tests/ui/mut_from_ref.rs
@@ -1,4 +1,4 @@
-#![allow(unused)]
+#![allow(unused, clippy::needless_lifetimes)]
 #![warn(clippy::mut_from_ref)]
 
 struct Foo;
diff --git a/src/tools/clippy/tests/ui/mut_mut.rs b/src/tools/clippy/tests/ui/mut_mut.rs
index ac8fd9d8fb0..ee3a856566c 100644
--- a/src/tools/clippy/tests/ui/mut_mut.rs
+++ b/src/tools/clippy/tests/ui/mut_mut.rs
@@ -57,3 +57,20 @@ fn issue6922() {
     // do not lint from an external macro
     mut_mut!();
 }
+
+mod issue9035 {
+    use std::fmt::Display;
+
+    struct Foo<'a> {
+        inner: &'a mut dyn Display,
+    }
+
+    impl Foo<'_> {
+        fn foo(&mut self) {
+            let hlp = &mut self.inner;
+            bar(hlp);
+        }
+    }
+
+    fn bar(_: &mut impl Display) {}
+}
diff --git a/src/tools/clippy/tests/ui/mut_range_bound.rs b/src/tools/clippy/tests/ui/mut_range_bound.rs
index e1ae1ef9282..7fdeb27ed98 100644
--- a/src/tools/clippy/tests/ui/mut_range_bound.rs
+++ b/src/tools/clippy/tests/ui/mut_range_bound.rs
@@ -76,7 +76,7 @@ fn mut_range_bound_no_immediate_break() {
     let mut n = 3;
     for i in n..10 {
         if n == 4 {
-            n = 1; // FIXME: warning because is is not immediately followed by break
+            n = 1; // FIXME: warning because it is not immediately followed by break
             let _ = 2;
             break;
         }
diff --git a/src/tools/clippy/tests/ui/mut_range_bound.stderr b/src/tools/clippy/tests/ui/mut_range_bound.stderr
index e0c8dced382..b679b7a0aaf 100644
--- a/src/tools/clippy/tests/ui/mut_range_bound.stderr
+++ b/src/tools/clippy/tests/ui/mut_range_bound.stderr
@@ -50,7 +50,7 @@ LL |         m = 2; // warning because it is not immediately followed by break
 error: attempt to mutate range bound within loop
   --> $DIR/mut_range_bound.rs:79:13
    |
-LL |             n = 1; // FIXME: warning because is is not immediately followed by break
+LL |             n = 1; // FIXME: warning because it is not immediately followed by break
    |             ^
    |
    = note: the range of the loop is unchanged
diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed
index 340e89d2db1..85b6b639d55 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrow.fixed
@@ -385,3 +385,128 @@ mod used_more_than_once {
     fn use_x(_: impl AsRef<str>) {}
     fn use_x_again(_: impl AsRef<str>) {}
 }
+
+// https://github.com/rust-lang/rust-clippy/issues/9111#issuecomment-1277114280
+#[allow(dead_code)]
+mod issue_9111 {
+    struct A;
+
+    impl Extend<u8> for A {
+        fn extend<T: IntoIterator<Item = u8>>(&mut self, _: T) {
+            unimplemented!()
+        }
+    }
+
+    impl<'a> Extend<&'a u8> for A {
+        fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, _: T) {
+            unimplemented!()
+        }
+    }
+
+    fn main() {
+        let mut a = A;
+        a.extend(&[]); // vs a.extend([]);
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9710 {
+    fn main() {
+        let string = String::new();
+        for _i in 0..10 {
+            f(&string);
+        }
+    }
+
+    fn f<T: AsRef<str>>(_: T) {}
+}
+
+#[allow(dead_code)]
+mod issue_9739 {
+    fn foo<D: std::fmt::Display>(_it: impl IntoIterator<Item = D>) {}
+
+    fn main() {
+        foo(if std::env::var_os("HI").is_some() {
+            &[0]
+        } else {
+            &[] as &[u32]
+        });
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9739_method_variant {
+    struct S;
+
+    impl S {
+        fn foo<D: std::fmt::Display>(&self, _it: impl IntoIterator<Item = D>) {}
+    }
+
+    fn main() {
+        S.foo(if std::env::var_os("HI").is_some() {
+            &[0]
+        } else {
+            &[] as &[u32]
+        });
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9782 {
+    fn foo<T: AsRef<[u8]>>(t: T) {
+        println!("{}", std::mem::size_of::<T>());
+        let _t: &[u8] = t.as_ref();
+    }
+
+    fn main() {
+        let a: [u8; 100] = [0u8; 100];
+
+        // 100
+        foo::<[u8; 100]>(a);
+        foo(a);
+
+        // 16
+        foo::<&[u8]>(&a);
+        foo(a.as_slice());
+
+        // 8
+        foo::<&[u8; 100]>(&a);
+        foo(a);
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9782_type_relative_variant {
+    struct S;
+
+    impl S {
+        fn foo<T: AsRef<[u8]>>(t: T) {
+            println!("{}", std::mem::size_of::<T>());
+            let _t: &[u8] = t.as_ref();
+        }
+    }
+
+    fn main() {
+        let a: [u8; 100] = [0u8; 100];
+
+        S::foo::<&[u8; 100]>(&a);
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9782_method_variant {
+    struct S;
+
+    impl S {
+        fn foo<T: AsRef<[u8]>>(&self, t: T) {
+            println!("{}", std::mem::size_of::<T>());
+            let _t: &[u8] = t.as_ref();
+        }
+    }
+
+    fn main() {
+        let a: [u8; 100] = [0u8; 100];
+
+        S.foo::<&[u8; 100]>(&a);
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs
index c93711ac8e2..7b97bcf3817 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.rs
+++ b/src/tools/clippy/tests/ui/needless_borrow.rs
@@ -385,3 +385,128 @@ mod used_more_than_once {
     fn use_x(_: impl AsRef<str>) {}
     fn use_x_again(_: impl AsRef<str>) {}
 }
+
+// https://github.com/rust-lang/rust-clippy/issues/9111#issuecomment-1277114280
+#[allow(dead_code)]
+mod issue_9111 {
+    struct A;
+
+    impl Extend<u8> for A {
+        fn extend<T: IntoIterator<Item = u8>>(&mut self, _: T) {
+            unimplemented!()
+        }
+    }
+
+    impl<'a> Extend<&'a u8> for A {
+        fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, _: T) {
+            unimplemented!()
+        }
+    }
+
+    fn main() {
+        let mut a = A;
+        a.extend(&[]); // vs a.extend([]);
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9710 {
+    fn main() {
+        let string = String::new();
+        for _i in 0..10 {
+            f(&string);
+        }
+    }
+
+    fn f<T: AsRef<str>>(_: T) {}
+}
+
+#[allow(dead_code)]
+mod issue_9739 {
+    fn foo<D: std::fmt::Display>(_it: impl IntoIterator<Item = D>) {}
+
+    fn main() {
+        foo(if std::env::var_os("HI").is_some() {
+            &[0]
+        } else {
+            &[] as &[u32]
+        });
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9739_method_variant {
+    struct S;
+
+    impl S {
+        fn foo<D: std::fmt::Display>(&self, _it: impl IntoIterator<Item = D>) {}
+    }
+
+    fn main() {
+        S.foo(if std::env::var_os("HI").is_some() {
+            &[0]
+        } else {
+            &[] as &[u32]
+        });
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9782 {
+    fn foo<T: AsRef<[u8]>>(t: T) {
+        println!("{}", std::mem::size_of::<T>());
+        let _t: &[u8] = t.as_ref();
+    }
+
+    fn main() {
+        let a: [u8; 100] = [0u8; 100];
+
+        // 100
+        foo::<[u8; 100]>(a);
+        foo(a);
+
+        // 16
+        foo::<&[u8]>(&a);
+        foo(a.as_slice());
+
+        // 8
+        foo::<&[u8; 100]>(&a);
+        foo(&a);
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9782_type_relative_variant {
+    struct S;
+
+    impl S {
+        fn foo<T: AsRef<[u8]>>(t: T) {
+            println!("{}", std::mem::size_of::<T>());
+            let _t: &[u8] = t.as_ref();
+        }
+    }
+
+    fn main() {
+        let a: [u8; 100] = [0u8; 100];
+
+        S::foo::<&[u8; 100]>(&a);
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9782_method_variant {
+    struct S;
+
+    impl S {
+        fn foo<T: AsRef<[u8]>>(&self, t: T) {
+            println!("{}", std::mem::size_of::<T>());
+            let _t: &[u8] = t.as_ref();
+        }
+    }
+
+    fn main() {
+        let a: [u8; 100] = [0u8; 100];
+
+        S.foo::<&[u8; 100]>(&a);
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr
index 8b593268bec..485e6b84c86 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.stderr
+++ b/src/tools/clippy/tests/ui/needless_borrow.stderr
@@ -210,5 +210,11 @@ error: the borrowed expression implements the required traits
 LL |         use_x(&x);
    |               ^^ help: change this to: `x`
 
-error: aborting due to 35 previous errors
+error: the borrowed expression implements the required traits
+  --> $DIR/needless_borrow.rs:474:13
+   |
+LL |         foo(&a);
+   |             ^^ help: change this to: `a`
+
+error: aborting due to 36 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed b/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
index bcb4eb2dd48..0c47ceb7b67 100644
--- a/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
@@ -1,11 +1,32 @@
 // run-rustfix
 
 #![warn(clippy::needless_borrowed_reference)]
-#![allow(unused, clippy::needless_borrow)]
+#![allow(
+    unused,
+    irrefutable_let_patterns,
+    non_shorthand_field_patterns,
+    clippy::needless_borrow
+)]
 
 fn main() {}
 
-fn should_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
+struct Struct {
+    a: usize,
+    b: usize,
+    c: usize,
+}
+
+struct TupleStruct(u8, u8, u8);
+
+fn should_lint(
+    array: [u8; 4],
+    slice: &[u8],
+    slice_of_refs: &[&u8],
+    vec: Vec<u8>,
+    tuple: (u8, u8, u8),
+    tuple_struct: TupleStruct,
+    s: Struct,
+) {
     let mut v = Vec::<String>::new();
     let _ = v.iter_mut().filter(|a| a.is_empty());
 
@@ -24,16 +45,54 @@ fn should_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>
     if let [a, b, ..] = slice {}
     if let [a, .., b] = slice {}
     if let [.., a, b] = slice {}
+
+    if let [a, _] = slice {}
+
+    if let (a, b, c) = &tuple {}
+    if let (a, _, c) = &tuple {}
+    if let (a, ..) = &tuple {}
+
+    if let TupleStruct(a, ..) = &tuple_struct {}
+
+    if let Struct {
+        a,
+        b: b,
+        c: renamed,
+    } = &s
+    {}
+
+    if let Struct { a, b: _, .. } = &s {}
 }
 
-fn should_not_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
+fn should_not_lint(
+    array: [u8; 4],
+    slice: &[u8],
+    slice_of_refs: &[&u8],
+    vec: Vec<u8>,
+    tuple: (u8, u8, u8),
+    tuple_struct: TupleStruct,
+    s: Struct,
+) {
     if let [ref a] = slice {}
     if let &[ref a, b] = slice {}
     if let &[ref a, .., b] = slice {}
 
+    if let &(ref a, b, ..) = &tuple {}
+    if let &TupleStruct(ref a, b, ..) = &tuple_struct {}
+    if let &Struct { ref a, b, .. } = &s {}
+
     // must not be removed as variables must be bound consistently across | patterns
     if let (&[ref a], _) | ([], ref a) = (slice_of_refs, &1u8) {}
 
+    // the `&`s here technically could be removed, but it'd be noisy and without a `ref` doesn't match
+    // the lint name
+    if let &[] = slice {}
+    if let &[_] = slice {}
+    if let &[..] = slice {}
+    if let &(..) = &tuple {}
+    if let &TupleStruct(..) = &tuple_struct {}
+    if let &Struct { .. } = &s {}
+
     let mut var2 = 5;
     let thingy2 = Some(&mut var2);
     if let Some(&mut ref mut v) = thingy2 {
@@ -59,6 +118,6 @@ fn foo(a: &Animal, b: &Animal) {
         // lifetime mismatch error if there is no '&ref' before `feature(nll)` stabilization in 1.63
         (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (),
         //                  ^    and   ^ should **not** be linted
-        (&Animal::Dog(ref a), &Animal::Dog(_)) => (), //              ^ should **not** be linted
+        (Animal::Dog(a), &Animal::Dog(_)) => (),
     }
 }
diff --git a/src/tools/clippy/tests/ui/needless_borrowed_ref.rs b/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
index f6de1a6d83d..f883bb0c889 100644
--- a/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
+++ b/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
@@ -1,11 +1,32 @@
 // run-rustfix
 
 #![warn(clippy::needless_borrowed_reference)]
-#![allow(unused, clippy::needless_borrow)]
+#![allow(
+    unused,
+    irrefutable_let_patterns,
+    non_shorthand_field_patterns,
+    clippy::needless_borrow
+)]
 
 fn main() {}
 
-fn should_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
+struct Struct {
+    a: usize,
+    b: usize,
+    c: usize,
+}
+
+struct TupleStruct(u8, u8, u8);
+
+fn should_lint(
+    array: [u8; 4],
+    slice: &[u8],
+    slice_of_refs: &[&u8],
+    vec: Vec<u8>,
+    tuple: (u8, u8, u8),
+    tuple_struct: TupleStruct,
+    s: Struct,
+) {
     let mut v = Vec::<String>::new();
     let _ = v.iter_mut().filter(|&ref a| a.is_empty());
 
@@ -24,16 +45,54 @@ fn should_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>
     if let &[ref a, ref b, ..] = slice {}
     if let &[ref a, .., ref b] = slice {}
     if let &[.., ref a, ref b] = slice {}
+
+    if let &[ref a, _] = slice {}
+
+    if let &(ref a, ref b, ref c) = &tuple {}
+    if let &(ref a, _, ref c) = &tuple {}
+    if let &(ref a, ..) = &tuple {}
+
+    if let &TupleStruct(ref a, ..) = &tuple_struct {}
+
+    if let &Struct {
+        ref a,
+        b: ref b,
+        c: ref renamed,
+    } = &s
+    {}
+
+    if let &Struct { ref a, b: _, .. } = &s {}
 }
 
-fn should_not_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
+fn should_not_lint(
+    array: [u8; 4],
+    slice: &[u8],
+    slice_of_refs: &[&u8],
+    vec: Vec<u8>,
+    tuple: (u8, u8, u8),
+    tuple_struct: TupleStruct,
+    s: Struct,
+) {
     if let [ref a] = slice {}
     if let &[ref a, b] = slice {}
     if let &[ref a, .., b] = slice {}
 
+    if let &(ref a, b, ..) = &tuple {}
+    if let &TupleStruct(ref a, b, ..) = &tuple_struct {}
+    if let &Struct { ref a, b, .. } = &s {}
+
     // must not be removed as variables must be bound consistently across | patterns
     if let (&[ref a], _) | ([], ref a) = (slice_of_refs, &1u8) {}
 
+    // the `&`s here technically could be removed, but it'd be noisy and without a `ref` doesn't match
+    // the lint name
+    if let &[] = slice {}
+    if let &[_] = slice {}
+    if let &[..] = slice {}
+    if let &(..) = &tuple {}
+    if let &TupleStruct(..) = &tuple_struct {}
+    if let &Struct { .. } = &s {}
+
     let mut var2 = 5;
     let thingy2 = Some(&mut var2);
     if let Some(&mut ref mut v) = thingy2 {
@@ -59,6 +118,6 @@ fn foo(a: &Animal, b: &Animal) {
         // lifetime mismatch error if there is no '&ref' before `feature(nll)` stabilization in 1.63
         (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (),
         //                  ^    and   ^ should **not** be linted
-        (&Animal::Dog(ref a), &Animal::Dog(_)) => (), //              ^ should **not** be linted
+        (Animal::Dog(a), &Animal::Dog(_)) => (),
     }
 }
diff --git a/src/tools/clippy/tests/ui/needless_borrowed_ref.stderr b/src/tools/clippy/tests/ui/needless_borrowed_ref.stderr
index 7453542e673..8d0f0c258dd 100644
--- a/src/tools/clippy/tests/ui/needless_borrowed_ref.stderr
+++ b/src/tools/clippy/tests/ui/needless_borrowed_ref.stderr
@@ -1,5 +1,5 @@
 error: this pattern takes a reference on something that is being dereferenced
-  --> $DIR/needless_borrowed_ref.rs:10:34
+  --> $DIR/needless_borrowed_ref.rs:31:34
    |
 LL |     let _ = v.iter_mut().filter(|&ref a| a.is_empty());
    |                                  ^^^^^^
@@ -12,7 +12,7 @@ LL +     let _ = v.iter_mut().filter(|a| a.is_empty());
    |
 
 error: this pattern takes a reference on something that is being dereferenced
-  --> $DIR/needless_borrowed_ref.rs:14:17
+  --> $DIR/needless_borrowed_ref.rs:35:17
    |
 LL |     if let Some(&ref v) = thingy {}
    |                 ^^^^^^
@@ -24,7 +24,7 @@ LL +     if let Some(v) = thingy {}
    |
 
 error: this pattern takes a reference on something that is being dereferenced
-  --> $DIR/needless_borrowed_ref.rs:16:14
+  --> $DIR/needless_borrowed_ref.rs:37:14
    |
 LL |     if let &[&ref a, ref b] = slice_of_refs {}
    |              ^^^^^^
@@ -36,7 +36,7 @@ LL +     if let &[a, ref b] = slice_of_refs {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:18:9
+  --> $DIR/needless_borrowed_ref.rs:39:9
    |
 LL |     let &[ref a, ..] = &array;
    |         ^^^^^^^^^^^^
@@ -48,7 +48,7 @@ LL +     let [a, ..] = &array;
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:19:9
+  --> $DIR/needless_borrowed_ref.rs:40:9
    |
 LL |     let &[ref a, ref b, ..] = &array;
    |         ^^^^^^^^^^^^^^^^^^^
@@ -60,7 +60,7 @@ LL +     let [a, b, ..] = &array;
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:21:12
+  --> $DIR/needless_borrowed_ref.rs:42:12
    |
 LL |     if let &[ref a, ref b] = slice {}
    |            ^^^^^^^^^^^^^^^
@@ -72,7 +72,7 @@ LL +     if let [a, b] = slice {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:22:12
+  --> $DIR/needless_borrowed_ref.rs:43:12
    |
 LL |     if let &[ref a, ref b] = &vec[..] {}
    |            ^^^^^^^^^^^^^^^
@@ -84,7 +84,7 @@ LL +     if let [a, b] = &vec[..] {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:24:12
+  --> $DIR/needless_borrowed_ref.rs:45:12
    |
 LL |     if let &[ref a, ref b, ..] = slice {}
    |            ^^^^^^^^^^^^^^^^^^^
@@ -96,7 +96,7 @@ LL +     if let [a, b, ..] = slice {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:25:12
+  --> $DIR/needless_borrowed_ref.rs:46:12
    |
 LL |     if let &[ref a, .., ref b] = slice {}
    |            ^^^^^^^^^^^^^^^^^^^
@@ -108,7 +108,7 @@ LL +     if let [a, .., b] = slice {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:26:12
+  --> $DIR/needless_borrowed_ref.rs:47:12
    |
 LL |     if let &[.., ref a, ref b] = slice {}
    |            ^^^^^^^^^^^^^^^^^^^
@@ -119,5 +119,96 @@ LL -     if let &[.., ref a, ref b] = slice {}
 LL +     if let [.., a, b] = slice {}
    |
 
-error: aborting due to 10 previous errors
+error: dereferencing a slice pattern where every element takes a reference
+  --> $DIR/needless_borrowed_ref.rs:49:12
+   |
+LL |     if let &[ref a, _] = slice {}
+   |            ^^^^^^^^^^^
+   |
+help: try removing the `&` and `ref` parts
+   |
+LL -     if let &[ref a, _] = slice {}
+LL +     if let [a, _] = slice {}
+   |
+
+error: dereferencing a tuple pattern where every element takes a reference
+  --> $DIR/needless_borrowed_ref.rs:51:12
+   |
+LL |     if let &(ref a, ref b, ref c) = &tuple {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try removing the `&` and `ref` parts
+   |
+LL -     if let &(ref a, ref b, ref c) = &tuple {}
+LL +     if let (a, b, c) = &tuple {}
+   |
+
+error: dereferencing a tuple pattern where every element takes a reference
+  --> $DIR/needless_borrowed_ref.rs:52:12
+   |
+LL |     if let &(ref a, _, ref c) = &tuple {}
+   |            ^^^^^^^^^^^^^^^^^^
+   |
+help: try removing the `&` and `ref` parts
+   |
+LL -     if let &(ref a, _, ref c) = &tuple {}
+LL +     if let (a, _, c) = &tuple {}
+   |
+
+error: dereferencing a tuple pattern where every element takes a reference
+  --> $DIR/needless_borrowed_ref.rs:53:12
+   |
+LL |     if let &(ref a, ..) = &tuple {}
+   |            ^^^^^^^^^^^^
+   |
+help: try removing the `&` and `ref` parts
+   |
+LL -     if let &(ref a, ..) = &tuple {}
+LL +     if let (a, ..) = &tuple {}
+   |
+
+error: dereferencing a tuple pattern where every element takes a reference
+  --> $DIR/needless_borrowed_ref.rs:55:12
+   |
+LL |     if let &TupleStruct(ref a, ..) = &tuple_struct {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try removing the `&` and `ref` parts
+   |
+LL -     if let &TupleStruct(ref a, ..) = &tuple_struct {}
+LL +     if let TupleStruct(a, ..) = &tuple_struct {}
+   |
+
+error: dereferencing a struct pattern where every field's pattern takes a reference
+  --> $DIR/needless_borrowed_ref.rs:57:12
+   |
+LL |       if let &Struct {
+   |  ____________^
+LL | |         ref a,
+LL | |         b: ref b,
+LL | |         c: ref renamed,
+LL | |     } = &s
+   | |_____^
+   |
+help: try removing the `&` and `ref` parts
+   |
+LL ~     if let Struct {
+LL ~         a,
+LL ~         b: b,
+LL ~         c: renamed,
+   |
+
+error: dereferencing a struct pattern where every field's pattern takes a reference
+  --> $DIR/needless_borrowed_ref.rs:64:12
+   |
+LL |     if let &Struct { ref a, b: _, .. } = &s {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try removing the `&` and `ref` parts
+   |
+LL -     if let &Struct { ref a, b: _, .. } = &s {}
+LL +     if let Struct { a, b: _, .. } = &s {}
+   |
+
+error: aborting due to 17 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_collect.fixed b/src/tools/clippy/tests/ui/needless_collect.fixed
index 6ecbbcb6249..2659ad38488 100644
--- a/src/tools/clippy/tests/ui/needless_collect.fixed
+++ b/src/tools/clippy/tests/ui/needless_collect.fixed
@@ -33,4 +33,33 @@ fn main() {
     // `BinaryHeap` doesn't have `contains` method
     sample.iter().count();
     sample.iter().next().is_none();
+
+    // Don't lint string from str
+    let _ = ["", ""].into_iter().collect::<String>().is_empty();
+
+    let _ = sample.iter().next().is_none();
+    let _ = sample.iter().any(|x| x == &0);
+
+    struct VecWrapper<T>(Vec<T>);
+    impl<T> core::ops::Deref for VecWrapper<T> {
+        type Target = Vec<T>;
+        fn deref(&self) -> &Self::Target {
+            &self.0
+        }
+    }
+    impl<T> IntoIterator for VecWrapper<T> {
+        type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
+        type Item = <Vec<T> as IntoIterator>::Item;
+        fn into_iter(self) -> Self::IntoIter {
+            self.0.into_iter()
+        }
+    }
+    impl<T> FromIterator<T> for VecWrapper<T> {
+        fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
+            Self(Vec::from_iter(iter))
+        }
+    }
+
+    let _ = sample.iter().next().is_none();
+    let _ = sample.iter().any(|x| x == &0);
 }
diff --git a/src/tools/clippy/tests/ui/needless_collect.rs b/src/tools/clippy/tests/ui/needless_collect.rs
index 8dc69bcf5b3..535ec82982b 100644
--- a/src/tools/clippy/tests/ui/needless_collect.rs
+++ b/src/tools/clippy/tests/ui/needless_collect.rs
@@ -33,4 +33,33 @@ fn main() {
     // `BinaryHeap` doesn't have `contains` method
     sample.iter().collect::<BinaryHeap<_>>().len();
     sample.iter().collect::<BinaryHeap<_>>().is_empty();
+
+    // Don't lint string from str
+    let _ = ["", ""].into_iter().collect::<String>().is_empty();
+
+    let _ = sample.iter().collect::<HashSet<_>>().is_empty();
+    let _ = sample.iter().collect::<HashSet<_>>().contains(&&0);
+
+    struct VecWrapper<T>(Vec<T>);
+    impl<T> core::ops::Deref for VecWrapper<T> {
+        type Target = Vec<T>;
+        fn deref(&self) -> &Self::Target {
+            &self.0
+        }
+    }
+    impl<T> IntoIterator for VecWrapper<T> {
+        type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
+        type Item = <Vec<T> as IntoIterator>::Item;
+        fn into_iter(self) -> Self::IntoIter {
+            self.0.into_iter()
+        }
+    }
+    impl<T> FromIterator<T> for VecWrapper<T> {
+        fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
+            Self(Vec::from_iter(iter))
+        }
+    }
+
+    let _ = sample.iter().collect::<VecWrapper<_>>().is_empty();
+    let _ = sample.iter().collect::<VecWrapper<_>>().contains(&&0);
 }
diff --git a/src/tools/clippy/tests/ui/needless_collect.stderr b/src/tools/clippy/tests/ui/needless_collect.stderr
index 039091627a8..584d2a1d835 100644
--- a/src/tools/clippy/tests/ui/needless_collect.stderr
+++ b/src/tools/clippy/tests/ui/needless_collect.stderr
@@ -66,5 +66,29 @@ error: avoid using `collect()` when not needed
 LL |     sample.iter().collect::<BinaryHeap<_>>().is_empty();
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()`
 
-error: aborting due to 11 previous errors
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:40:27
+   |
+LL |     let _ = sample.iter().collect::<HashSet<_>>().is_empty();
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()`
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:41:27
+   |
+LL |     let _ = sample.iter().collect::<HashSet<_>>().contains(&&0);
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &0)`
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:63:27
+   |
+LL |     let _ = sample.iter().collect::<VecWrapper<_>>().is_empty();
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()`
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:64:27
+   |
+LL |     let _ = sample.iter().collect::<VecWrapper<_>>().contains(&&0);
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &0)`
+
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_collect_indirect.rs b/src/tools/clippy/tests/ui/needless_collect_indirect.rs
index 6d213b46c20..fe4209e99b2 100644
--- a/src/tools/clippy/tests/ui/needless_collect_indirect.rs
+++ b/src/tools/clippy/tests/ui/needless_collect_indirect.rs
@@ -1,4 +1,5 @@
 #![allow(clippy::uninlined_format_args)]
+#![warn(clippy::needless_collect)]
 
 use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
 
diff --git a/src/tools/clippy/tests/ui/needless_collect_indirect.stderr b/src/tools/clippy/tests/ui/needless_collect_indirect.stderr
index 99e1b91d8fe..790d725907f 100644
--- a/src/tools/clippy/tests/ui/needless_collect_indirect.stderr
+++ b/src/tools/clippy/tests/ui/needless_collect_indirect.stderr
@@ -1,5 +1,5 @@
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:7:39
+  --> $DIR/needless_collect_indirect.rs:8:39
    |
 LL |     let indirect_iter = sample.iter().collect::<Vec<_>>();
    |                                       ^^^^^^^
@@ -14,7 +14,7 @@ LL ~     sample.iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>();
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:9:38
+  --> $DIR/needless_collect_indirect.rs:10:38
    |
 LL |     let indirect_len = sample.iter().collect::<VecDeque<_>>();
    |                                      ^^^^^^^
@@ -28,7 +28,7 @@ LL ~     sample.iter().count();
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:11:40
+  --> $DIR/needless_collect_indirect.rs:12:40
    |
 LL |     let indirect_empty = sample.iter().collect::<VecDeque<_>>();
    |                                        ^^^^^^^
@@ -42,7 +42,7 @@ LL ~     sample.iter().next().is_none();
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:13:43
+  --> $DIR/needless_collect_indirect.rs:14:43
    |
 LL |     let indirect_contains = sample.iter().collect::<VecDeque<_>>();
    |                                           ^^^^^^^
@@ -56,7 +56,7 @@ LL ~     sample.iter().any(|x| x == &5);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:25:48
+  --> $DIR/needless_collect_indirect.rs:26:48
    |
 LL |     let non_copy_contains = sample.into_iter().collect::<Vec<_>>();
    |                                                ^^^^^^^
@@ -70,7 +70,7 @@ LL ~     sample.into_iter().any(|x| x == a);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:54:51
+  --> $DIR/needless_collect_indirect.rs:55:51
    |
 LL |         let buffer: Vec<&str> = string.split('/').collect();
    |                                                   ^^^^^^^
@@ -84,7 +84,7 @@ LL ~         string.split('/').count()
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:59:55
+  --> $DIR/needless_collect_indirect.rs:60:55
    |
 LL |         let indirect_len: VecDeque<_> = sample.iter().collect();
    |                                                       ^^^^^^^
@@ -98,7 +98,7 @@ LL ~         sample.iter().count()
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:64:57
+  --> $DIR/needless_collect_indirect.rs:65:57
    |
 LL |         let indirect_len: LinkedList<_> = sample.iter().collect();
    |                                                         ^^^^^^^
@@ -112,7 +112,7 @@ LL ~         sample.iter().count()
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:69:57
+  --> $DIR/needless_collect_indirect.rs:70:57
    |
 LL |         let indirect_len: BinaryHeap<_> = sample.iter().collect();
    |                                                         ^^^^^^^
@@ -126,7 +126,7 @@ LL ~         sample.iter().count()
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:129:59
+  --> $DIR/needless_collect_indirect.rs:130:59
    |
 LL |             let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                           ^^^^^^^
@@ -143,7 +143,7 @@ LL ~             vec.iter().map(|k| k * k).any(|x| x == i);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:154:59
+  --> $DIR/needless_collect_indirect.rs:155:59
    |
 LL |             let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                           ^^^^^^^
@@ -160,7 +160,7 @@ LL ~             vec.iter().map(|k| k * k).any(|x| x == n);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:183:63
+  --> $DIR/needless_collect_indirect.rs:184:63
    |
 LL |                 let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                               ^^^^^^^
@@ -177,7 +177,7 @@ LL ~                 vec.iter().map(|k| k * k).any(|x| x == n);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:219:59
+  --> $DIR/needless_collect_indirect.rs:220:59
    |
 LL |             let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                           ^^^^^^^
@@ -195,7 +195,7 @@ LL ~                 vec.iter().map(|k| k * k).any(|x| x == n);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:244:26
+  --> $DIR/needless_collect_indirect.rs:245:26
    |
 LL |         let w = v.iter().collect::<Vec<_>>();
    |                          ^^^^^^^
@@ -211,7 +211,7 @@ LL ~         for _ in 0..v.iter().count() {
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:266:30
+  --> $DIR/needless_collect_indirect.rs:267:30
    |
 LL |         let mut w = v.iter().collect::<Vec<_>>();
    |                              ^^^^^^^
@@ -227,7 +227,7 @@ LL ~         while 1 == v.iter().count() {
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:288:30
+  --> $DIR/needless_collect_indirect.rs:289:30
    |
 LL |         let mut w = v.iter().collect::<Vec<_>>();
    |                              ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.rs b/src/tools/clippy/tests/ui/needless_lifetimes.rs
index fc686b1dac0..2efc936752e 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.rs
@@ -29,11 +29,20 @@ fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 {
     x
 }
 
-// No error; multiple input refs.
-fn multiple_in_and_out_2<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+//   fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8
+//                                                ^^^
+fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
     x
 }
 
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+//   fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8
+//                                     ^^^
+fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
+    y
+}
+
 // No error; multiple input refs
 async fn func<'a>(args: &[&'a str]) -> Option<&'a str> {
     args.get(0).cloned()
@@ -44,11 +53,20 @@ fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 {
     x
 }
 
-// No error.
-fn deep_reference_1<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+//   fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()>
+//                                           ^^^
+fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
     Ok(x)
 }
 
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+//   fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()>
+//                                ^^^
+fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
+    Ok(y)
+}
+
 // No error; two input refs.
 fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 {
     x.unwrap()
@@ -129,11 +147,20 @@ impl X {
         &self.x
     }
 
-    // No error; multiple input refs.
-    fn self_and_in_out<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
+    // Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+    //   fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8
+    //                                          ^^^
+    fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
         &self.x
     }
 
+    // Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+    //   fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8
+    //                            ^^^^^
+    fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
+        x
+    }
+
     fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
 
     // No error; same lifetimes on two params.
@@ -167,8 +194,19 @@ fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str {
     unimplemented!()
 }
 
-// No warning; two input lifetimes.
-fn struct_with_lt4<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+//   fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str
+//                                         ^^
+fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
+    unimplemented!()
+}
+
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+//   fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str
+//                                 ^^^^
+fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
     unimplemented!()
 }
 
@@ -203,8 +241,19 @@ fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str {
     unimplemented!()
 }
 
-// No warning; two input lifetimes.
-fn alias_with_lt4<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+//   fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str
+//                                             ^^
+fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
+    unimplemented!()
+}
+
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+//   fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str
+//                                ^^^^^^^^^
+fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
     unimplemented!()
 }
 
@@ -419,4 +468,31 @@ mod issue7296 {
     }
 }
 
+mod pr_9743_false_negative_fix {
+    #![allow(unused)]
+
+    fn foo<'a>(x: &'a u8, y: &'_ u8) {}
+
+    fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
+}
+
+mod pr_9743_output_lifetime_checks {
+    #![allow(unused)]
+
+    // lint: only one input
+    fn one_input<'a>(x: &'a u8) -> &'a u8 {
+        unimplemented!()
+    }
+
+    // lint: multiple inputs, output would not be elided
+    fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
+        unimplemented!()
+    }
+
+    // don't lint: multiple inputs, output would be elided (which would create an ambiguity)
+    fn multiple_inputs_output_would_be_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'a u8 {
+        unimplemented!()
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.stderr b/src/tools/clippy/tests/ui/needless_lifetimes.stderr
index 3c428fd4674..5a7cf13c86d 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.stderr
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.stderr
@@ -1,4 +1,4 @@
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+error: the following explicit lifetimes could be elided: 'a, 'b
   --> $DIR/needless_lifetimes.rs:11:1
    |
 LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
@@ -6,185 +6,311 @@ LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
    |
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+error: the following explicit lifetimes could be elided: 'a, 'b
   --> $DIR/needless_lifetimes.rs:13:1
    |
 LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+error: the following explicit lifetimes could be elided: 'a
   --> $DIR/needless_lifetimes.rs:23:1
    |
 LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:57:1
+error: the following explicit lifetimes could be elided: 'b
+  --> $DIR/needless_lifetimes.rs:35:1
+   |
+LL | fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:42:1
+   |
+LL | fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'b
+  --> $DIR/needless_lifetimes.rs:59:1
+   |
+LL | fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:66:1
+   |
+LL | fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:75:1
    |
 LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:62:1
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:80:1
    |
 LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:74:1
+error: the following explicit lifetimes could be elided: 'a, 'b
+  --> $DIR/needless_lifetimes.rs:92:1
    |
 LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace with `'_` in generic arguments such as here
+  --> $DIR/needless_lifetimes.rs:92:37
+   |
+LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
+   |                                     ^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:98:1
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:116:1
    |
 LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace with `'_` in generic arguments such as here
+  --> $DIR/needless_lifetimes.rs:116:32
+   |
+LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
+   |                                ^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:128:5
+error: the following explicit lifetimes could be elided: 's
+  --> $DIR/needless_lifetimes.rs:146:5
    |
 LL |     fn self_and_out<'s>(&'s self) -> &'s u8 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:137:5
+error: the following explicit lifetimes could be elided: 't
+  --> $DIR/needless_lifetimes.rs:153:5
+   |
+LL |     fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 's
+  --> $DIR/needless_lifetimes.rs:160:5
+   |
+LL |     fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 's, 't
+  --> $DIR/needless_lifetimes.rs:164:5
    |
 LL |     fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:156:1
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:183:1
    |
 LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace with `'_` in generic arguments such as here
+  --> $DIR/needless_lifetimes.rs:183:33
+   |
+LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
+   |                                 ^^
+
+error: the following explicit lifetimes could be elided: 'b
+  --> $DIR/needless_lifetimes.rs:201:1
+   |
+LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace with `'_` in generic arguments such as here
+  --> $DIR/needless_lifetimes.rs:201:43
+   |
+LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
+   |                                           ^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:209:1
+   |
+LL | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:186:1
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:224:1
    |
 LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:192:1
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:230:1
    |
 LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace with `'_` in generic arguments such as here
+  --> $DIR/needless_lifetimes.rs:230:37
+   |
+LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
+   |                                     ^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:211:1
+error: the following explicit lifetimes could be elided: 'b
+  --> $DIR/needless_lifetimes.rs:248:1
+   |
+LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace with `'_` in generic arguments such as here
+  --> $DIR/needless_lifetimes.rs:248:47
+   |
+LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
+   |                                               ^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:256:1
+   |
+LL | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:260:1
    |
 LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:219:1
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:268:1
    |
 LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:255:1
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:304:1
    |
 LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace with `'_` in generic arguments such as here
+  --> $DIR/needless_lifetimes.rs:304:47
+   |
+LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
+   |                                               ^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:262:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:311:9
    |
 LL |         fn needless_lt<'a>(x: &'a u8) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:266:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:315:9
    |
 LL |         fn needless_lt<'a>(_x: &'a u8) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:279:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:328:9
    |
 LL |         fn baz<'a>(&'a self) -> impl Foo + 'a {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:311:5
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:360:5
    |
 LL |     fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:320:5
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:369:5
    |
 LL |     fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:332:5
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:381:5
    |
 LL |     fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:347:5
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:396:5
    |
 LL |     fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:360:5
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:409:5
    |
 LL |     fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:363:5
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:412:5
    |
 LL |     fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:385:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:434:9
    |
 LL |         fn implicit<'a>(&'a self) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:388:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:437:9
    |
 LL |         fn implicit_mut<'a>(&'a mut self) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:399:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:448:9
    |
 LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:405:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:454:9
    |
 LL |         fn implicit<'a>(&'a self) -> &'a ();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:406:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:455:9
    |
 LL |         fn implicit_provided<'a>(&'a self) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:415:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:464:9
    |
 LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:416:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:465:9
    |
 LL |         fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 31 previous errors
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:474:5
+   |
+LL |     fn foo<'a>(x: &'a u8, y: &'_ u8) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:476:5
+   |
+LL |     fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:483:5
+   |
+LL |     fn one_input<'a>(x: &'a u8) -> &'a u8 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:488:5
+   |
+LL |     fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 45 previous errors
 
diff --git a/src/tools/clippy/tests/ui/never_loop.rs b/src/tools/clippy/tests/ui/never_loop.rs
index 3dbef19890e..28e8f459d44 100644
--- a/src/tools/clippy/tests/ui/never_loop.rs
+++ b/src/tools/clippy/tests/ui/never_loop.rs
@@ -229,6 +229,27 @@ pub fn test18() {
     };
 }
 
+// Issue #9831: unconditional break to internal labeled block
+pub fn test19() {
+    fn thing(iter: impl Iterator) {
+        for _ in iter {
+            'b: {
+                break 'b;
+            }
+        }
+    }
+}
+
+pub fn test20() {
+    'a: loop {
+        'b: {
+            break 'b 'c: {
+                break 'a;
+            };
+        }
+    }
+}
+
 fn main() {
     test1();
     test2();
diff --git a/src/tools/clippy/tests/ui/never_loop.stderr b/src/tools/clippy/tests/ui/never_loop.stderr
index 3033f019244..b7029bf8bed 100644
--- a/src/tools/clippy/tests/ui/never_loop.stderr
+++ b/src/tools/clippy/tests/ui/never_loop.stderr
@@ -114,5 +114,17 @@ LL | |         break x;
 LL | |     };
    | |_____^
 
-error: aborting due to 10 previous errors
+error: this loop never actually loops
+  --> $DIR/never_loop.rs:244:5
+   |
+LL | /     'a: loop {
+LL | |         'b: {
+LL | |             break 'b 'c: {
+LL | |                 break 'a;
+LL | |             };
+LL | |         }
+LL | |     }
+   | |_____^
+
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/new_ret_no_self.rs b/src/tools/clippy/tests/ui/new_ret_no_self.rs
index 2f315ffe298..f69982d63a8 100644
--- a/src/tools/clippy/tests/ui/new_ret_no_self.rs
+++ b/src/tools/clippy/tests/ui/new_ret_no_self.rs
@@ -350,3 +350,53 @@ impl RetOtherSelf<T> {
         RetOtherSelf(RetOtherSelfWrapper(t))
     }
 }
+
+mod issue7344 {
+    struct RetImplTraitSelf<T>(T);
+
+    impl<T> RetImplTraitSelf<T> {
+        // should not trigger lint
+        fn new(t: T) -> impl Into<Self> {
+            Self(t)
+        }
+    }
+
+    struct RetImplTraitNoSelf<T>(T);
+
+    impl<T> RetImplTraitNoSelf<T> {
+        // should trigger lint
+        fn new(t: T) -> impl Into<i32> {
+            1
+        }
+    }
+
+    trait Trait2<T, U> {}
+    impl<T, U> Trait2<T, U> for () {}
+
+    struct RetImplTraitSelf2<T>(T);
+
+    impl<T> RetImplTraitSelf2<T> {
+        // should not trigger lint
+        fn new(t: T) -> impl Trait2<(), Self> {
+            unimplemented!()
+        }
+    }
+
+    struct RetImplTraitNoSelf2<T>(T);
+
+    impl<T> RetImplTraitNoSelf2<T> {
+        // should trigger lint
+        fn new(t: T) -> impl Trait2<(), i32> {
+            unimplemented!()
+        }
+    }
+
+    struct RetImplTraitSelfAdt<'a>(&'a str);
+
+    impl<'a> RetImplTraitSelfAdt<'a> {
+        // should not trigger lint
+        fn new<'b: 'a>(s: &'b str) -> impl Into<RetImplTraitSelfAdt<'b>> {
+            RetImplTraitSelfAdt(s)
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/new_ret_no_self.stderr b/src/tools/clippy/tests/ui/new_ret_no_self.stderr
index 8217bc6187f..bc13be47927 100644
--- a/src/tools/clippy/tests/ui/new_ret_no_self.stderr
+++ b/src/tools/clippy/tests/ui/new_ret_no_self.stderr
@@ -76,5 +76,21 @@ LL | |             unimplemented!();
 LL | |         }
    | |_________^
 
-error: aborting due to 10 previous errors
+error: methods called `new` usually return `Self`
+  --> $DIR/new_ret_no_self.rs:368:9
+   |
+LL | /         fn new(t: T) -> impl Into<i32> {
+LL | |             1
+LL | |         }
+   | |_________^
+
+error: methods called `new` usually return `Self`
+  --> $DIR/new_ret_no_self.rs:389:9
+   |
+LL | /         fn new(t: T) -> impl Trait2<(), i32> {
+LL | |             unimplemented!()
+LL | |         }
+   | |_________^
+
+error: aborting due to 12 previous errors
 
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 f15ac551bb3..0456005dce4 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.fixed
+++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed
@@ -189,3 +189,12 @@ fn main() {
     let _ = res.map_or(1, |a| a + 1);
     let _ = res.map_or(5, |a| a + 1);
 }
+
+#[allow(dead_code)]
+fn issue9742() -> Option<&'static str> {
+    // should not lint because of guards
+    match Some("foo  ") {
+        Some(name) if name.starts_with("foo") => Some(name.trim()),
+        _ => 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 9eeaea12d3b..23b148752cb 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.rs
+++ b/src/tools/clippy/tests/ui/option_if_let_else.rs
@@ -230,3 +230,12 @@ fn main() {
     };
     let _ = if let Ok(a) = res { a + 1 } else { 5 };
 }
+
+#[allow(dead_code)]
+fn issue9742() -> Option<&'static str> {
+    // should not lint because of guards
+    match Some("foo  ") {
+        Some(name) if name.starts_with("foo") => Some(name.trim()),
+        _ => None,
+    }
+}
diff --git a/src/tools/clippy/tests/ui/or_fun_call.fixed b/src/tools/clippy/tests/ui/or_fun_call.fixed
index 23b1aa8bebd..be9a65506e1 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.fixed
+++ b/src/tools/clippy/tests/ui/or_fun_call.fixed
@@ -236,4 +236,20 @@ mod issue9608 {
     }
 }
 
+mod issue8993 {
+    fn g() -> i32 {
+        3
+    }
+
+    fn f(n: i32) -> i32 {
+        n
+    }
+
+    fn test_map_or() {
+        let _ = Some(4).map_or_else(g, |v| v);
+        let _ = Some(4).map_or_else(g, f);
+        let _ = Some(4).map_or(0, f);
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/or_fun_call.rs b/src/tools/clippy/tests/ui/or_fun_call.rs
index 039998f22dd..628c9704638 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.rs
+++ b/src/tools/clippy/tests/ui/or_fun_call.rs
@@ -236,4 +236,20 @@ mod issue9608 {
     }
 }
 
+mod issue8993 {
+    fn g() -> i32 {
+        3
+    }
+
+    fn f(n: i32) -> i32 {
+        n
+    }
+
+    fn test_map_or() {
+        let _ = Some(4).map_or(g(), |v| v);
+        let _ = Some(4).map_or(g(), f);
+        let _ = Some(4).map_or(0, f);
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/or_fun_call.stderr b/src/tools/clippy/tests/ui/or_fun_call.stderr
index 113ba150c61..ba3001db7a5 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.stderr
+++ b/src/tools/clippy/tests/ui/or_fun_call.stderr
@@ -156,5 +156,17 @@ error: use of `unwrap_or` followed by a call to `new`
 LL |         .unwrap_or(String::new());
    |          ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
 
-error: aborting due to 26 previous errors
+error: use of `map_or` followed by a function call
+  --> $DIR/or_fun_call.rs:249:25
+   |
+LL |         let _ = Some(4).map_or(g(), |v| v);
+   |                         ^^^^^^^^^^^^^^^^^^ help: try this: `map_or_else(g, |v| v)`
+
+error: use of `map_or` followed by a function call
+  --> $DIR/or_fun_call.rs:250:25
+   |
+LL |         let _ = Some(4).map_or(g(), f);
+   |                         ^^^^^^^^^^^^^^ help: try this: `map_or_else(g, f)`
+
+error: aborting due to 28 previous errors
 
diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed
index 993389232cc..5c49d46da72 100644
--- a/src/tools/clippy/tests/ui/question_mark.fixed
+++ b/src/tools/clippy/tests/ui/question_mark.fixed
@@ -134,6 +134,9 @@ fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
         return func_returning_result();
     }
 
+    // no warning
+    let _ = if let Err(e) = x { Err(e) } else { Ok(0) };
+
     Ok(y)
 }
 
diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs
index 9ae0d88829a..d057df6a9b3 100644
--- a/src/tools/clippy/tests/ui/question_mark.rs
+++ b/src/tools/clippy/tests/ui/question_mark.rs
@@ -166,6 +166,9 @@ fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
         return func_returning_result();
     }
 
+    // no warning
+    let _ = if let Err(e) = x { Err(e) } else { Ok(0) };
+
     Ok(y)
 }
 
diff --git a/src/tools/clippy/tests/ui/question_mark.stderr b/src/tools/clippy/tests/ui/question_mark.stderr
index 1b6cd524b2f..23172d7e535 100644
--- a/src/tools/clippy/tests/ui/question_mark.stderr
+++ b/src/tools/clippy/tests/ui/question_mark.stderr
@@ -115,7 +115,7 @@ LL | |     }
    | |_____^ help: replace it with: `x?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:193:5
+  --> $DIR/question_mark.rs:196:5
    |
 LL | /     if let Err(err) = func_returning_result() {
 LL | |         return Err(err);
@@ -123,7 +123,7 @@ LL | |     }
    | |_____^ help: replace it with: `func_returning_result()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:200:5
+  --> $DIR/question_mark.rs:203:5
    |
 LL | /     if let Err(err) = func_returning_result() {
 LL | |         return Err(err);
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 8beae8dee08..689928f0479 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -12,7 +12,6 @@
 #![allow(clippy::disallowed_methods)]
 #![allow(clippy::disallowed_types)]
 #![allow(clippy::mixed_read_write_in_expression)]
-#![allow(for_loops_over_fallibles)]
 #![allow(clippy::useless_conversion)]
 #![allow(clippy::match_result_ok)]
 #![allow(clippy::overly_complex_bool_expr)]
@@ -27,9 +26,11 @@
 #![allow(clippy::recursive_format_impl)]
 #![allow(clippy::invisible_characters)]
 #![allow(drop_bounds)]
+#![allow(for_loops_over_fallibles)]
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
+#![allow(let_underscore_drop)]
 #![allow(enum_intrinsics_non_enums)]
 #![allow(non_fmt_panics)]
 #![allow(named_arguments_used_positionally)]
@@ -45,8 +46,6 @@
 #![warn(clippy::disallowed_methods)]
 #![warn(clippy::disallowed_types)]
 #![warn(clippy::mixed_read_write_in_expression)]
-#![warn(for_loops_over_fallibles)]
-#![warn(for_loops_over_fallibles)]
 #![warn(clippy::useless_conversion)]
 #![warn(clippy::match_result_ok)]
 #![warn(clippy::overly_complex_bool_expr)]
@@ -66,9 +65,12 @@
 #![warn(clippy::invisible_characters)]
 #![warn(drop_bounds)]
 #![warn(for_loops_over_fallibles)]
+#![warn(for_loops_over_fallibles)]
+#![warn(for_loops_over_fallibles)]
 #![warn(array_into_iter)]
 #![warn(invalid_atomic_ordering)]
 #![warn(invalid_value)]
+#![warn(let_underscore_drop)]
 #![warn(enum_intrinsics_non_enums)]
 #![warn(non_fmt_panics)]
 #![warn(named_arguments_used_positionally)]
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 9e665047baa..b74aa650ffd 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -12,7 +12,6 @@
 #![allow(clippy::disallowed_methods)]
 #![allow(clippy::disallowed_types)]
 #![allow(clippy::mixed_read_write_in_expression)]
-#![allow(for_loops_over_fallibles)]
 #![allow(clippy::useless_conversion)]
 #![allow(clippy::match_result_ok)]
 #![allow(clippy::overly_complex_bool_expr)]
@@ -27,9 +26,11 @@
 #![allow(clippy::recursive_format_impl)]
 #![allow(clippy::invisible_characters)]
 #![allow(drop_bounds)]
+#![allow(for_loops_over_fallibles)]
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
+#![allow(let_underscore_drop)]
 #![allow(enum_intrinsics_non_enums)]
 #![allow(non_fmt_panics)]
 #![allow(named_arguments_used_positionally)]
@@ -45,8 +46,6 @@
 #![warn(clippy::disallowed_method)]
 #![warn(clippy::disallowed_type)]
 #![warn(clippy::eval_order_dependence)]
-#![warn(clippy::for_loop_over_option)]
-#![warn(clippy::for_loop_over_result)]
 #![warn(clippy::identity_conversion)]
 #![warn(clippy::if_let_some_result)]
 #![warn(clippy::logic_bug)]
@@ -65,10 +64,13 @@
 #![warn(clippy::to_string_in_display)]
 #![warn(clippy::zero_width_space)]
 #![warn(clippy::drop_bounds)]
+#![warn(clippy::for_loop_over_option)]
+#![warn(clippy::for_loop_over_result)]
 #![warn(clippy::for_loops_over_fallibles)]
 #![warn(clippy::into_iter_on_array)]
 #![warn(clippy::invalid_atomic_ordering)]
 #![warn(clippy::invalid_ref)]
+#![warn(clippy::let_underscore_drop)]
 #![warn(clippy::mem_discriminant_non_enum)]
 #![warn(clippy::panic_params)]
 #![warn(clippy::positional_named_format_parameters)]
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 63eb565185f..622a32c5908 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> $DIR/rename.rs:39:9
+  --> $DIR/rename.rs:40:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
@@ -7,232 +7,238 @@ LL | #![warn(clippy::blacklisted_name)]
    = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:40:9
+  --> $DIR/rename.rs:41: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:41:9
+  --> $DIR/rename.rs:42: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:42:9
+  --> $DIR/rename.rs:43: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:43:9
+  --> $DIR/rename.rs:44: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:44:9
+  --> $DIR/rename.rs:45:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> $DIR/rename.rs:45:9
+  --> $DIR/rename.rs:46: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:46:9
+  --> $DIR/rename.rs:47: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:47:9
+  --> $DIR/rename.rs:48:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
-error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:48: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:49:9
-   |
-LL | #![warn(clippy::for_loop_over_result)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
-
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> $DIR/rename.rs:50:9
+  --> $DIR/rename.rs:49: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:51:9
+  --> $DIR/rename.rs:50:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> $DIR/rename.rs:52:9
+  --> $DIR/rename.rs:51: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:53:9
+  --> $DIR/rename.rs:52: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:54:9
+  --> $DIR/rename.rs:53: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:55:9
+  --> $DIR/rename.rs:54: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:56:9
+  --> $DIR/rename.rs:55: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:57:9
+  --> $DIR/rename.rs:56: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:58:9
+  --> $DIR/rename.rs:57: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:59:9
+  --> $DIR/rename.rs:58: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:60:9
+  --> $DIR/rename.rs:59: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:61:9
+  --> $DIR/rename.rs:60: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:62:9
+  --> $DIR/rename.rs:61: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:63:9
+  --> $DIR/rename.rs:62: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:64:9
+  --> $DIR/rename.rs:63: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:65:9
+  --> $DIR/rename.rs:64: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:66:9
+  --> $DIR/rename.rs:65:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:67:9
+  --> $DIR/rename.rs:66:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
-error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
+error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
+  --> $DIR/rename.rs:67: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:68: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:69:9
+   |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:69:9
+  --> $DIR/rename.rs:70: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:70:9
+  --> $DIR/rename.rs:71: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:71:9
+  --> $DIR/rename.rs:72: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:73: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:72:9
+  --> $DIR/rename.rs:74: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:73:9
+  --> $DIR/rename.rs:75: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:74:9
+  --> $DIR/rename.rs:76: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:75:9
+  --> $DIR/rename.rs:77: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:76:9
+  --> $DIR/rename.rs:78: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:77:9
+  --> $DIR/rename.rs:79:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
-error: aborting due to 39 previous errors
+error: aborting due to 40 previous errors
 
diff --git a/src/tools/clippy/tests/ui/result_large_err.rs b/src/tools/clippy/tests/ui/result_large_err.rs
index f7df3b85655..9dd27d6dc01 100644
--- a/src/tools/clippy/tests/ui/result_large_err.rs
+++ b/src/tools/clippy/tests/ui/result_large_err.rs
@@ -50,6 +50,18 @@ impl LargeErrorVariants<()> {
     }
 }
 
+enum MultipleLargeVariants {
+    _Biggest([u8; 1024]),
+    _AlsoBig([u8; 512]),
+    _Ok(usize),
+}
+
+impl MultipleLargeVariants {
+    fn large_enum_error() -> Result<(), Self> {
+        Ok(())
+    }
+}
+
 trait TraitForcesLargeError {
     fn large_error() -> Result<(), [u8; 512]> {
         Ok(())
diff --git a/src/tools/clippy/tests/ui/result_large_err.stderr b/src/tools/clippy/tests/ui/result_large_err.stderr
index bea101fe20b..c386edfd215 100644
--- a/src/tools/clippy/tests/ui/result_large_err.stderr
+++ b/src/tools/clippy/tests/ui/result_large_err.stderr
@@ -42,13 +42,29 @@ LL | pub fn param_large_error<R>() -> Result<(), (u128, R, FullyDefinedLargeErro
 error: the `Err`-variant returned from this function is very large
   --> $DIR/result_large_err.rs:48:34
    |
+LL |     _Omg([u8; 512]),
+   |     --------------- the largest variant contains at least 512 bytes
+...
 LL |     pub fn large_enum_error() -> Result<(), Self> {
-   |                                  ^^^^^^^^^^^^^^^^ the `Err`-variant is at least 513 bytes
+   |                                  ^^^^^^^^^^^^^^^^
    |
    = help: try reducing the size of `LargeErrorVariants<()>`, for example by boxing large elements or replacing it with `Box<LargeErrorVariants<()>>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:54:25
+  --> $DIR/result_large_err.rs:60:30
+   |
+LL |     _Biggest([u8; 1024]),
+   |     -------------------- the largest variant contains at least 1024 bytes
+LL |     _AlsoBig([u8; 512]),
+   |     ------------------- the variant `_AlsoBig` contains at least 512 bytes
+...
+LL |     fn large_enum_error() -> Result<(), Self> {
+   |                              ^^^^^^^^^^^^^^^^
+   |
+   = help: try reducing the size of `MultipleLargeVariants`, for example by boxing large elements or replacing it with `Box<MultipleLargeVariants>`
+
+error: the `Err`-variant returned from this function is very large
+  --> $DIR/result_large_err.rs:66:25
    |
 LL |     fn large_error() -> Result<(), [u8; 512]> {
    |                         ^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
@@ -56,7 +72,7 @@ LL |     fn large_error() -> Result<(), [u8; 512]> {
    = help: try reducing the size of `[u8; 512]`, for example by boxing large elements or replacing it with `Box<[u8; 512]>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:73:29
+  --> $DIR/result_large_err.rs:85:29
    |
 LL | pub fn large_union_err() -> Result<(), FullyDefinedUnionError> {
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
@@ -64,7 +80,7 @@ LL | pub fn large_union_err() -> Result<(), FullyDefinedUnionError> {
    = help: try reducing the size of `FullyDefinedUnionError`, for example by boxing large elements or replacing it with `Box<FullyDefinedUnionError>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:82:40
+  --> $DIR/result_large_err.rs:94:40
    |
 LL | pub fn param_large_union<T: Copy>() -> Result<(), UnionError<T>> {
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
@@ -72,7 +88,7 @@ LL | pub fn param_large_union<T: Copy>() -> Result<(), UnionError<T>> {
    = help: try reducing the size of `UnionError<T>`, for example by boxing large elements or replacing it with `Box<UnionError<T>>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:91:34
+  --> $DIR/result_large_err.rs:103:34
    |
 LL | pub fn array_error_subst<U>() -> Result<(), ArrayError<i32, U>> {
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 128 bytes
@@ -80,12 +96,12 @@ LL | pub fn array_error_subst<U>() -> Result<(), ArrayError<i32, U>> {
    = help: try reducing the size of `ArrayError<i32, U>`, for example by boxing large elements or replacing it with `Box<ArrayError<i32, U>>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:95:31
+  --> $DIR/result_large_err.rs:107:31
    |
 LL | pub fn array_error<T, U>() -> Result<(), ArrayError<(i32, T), U>> {
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 128 bytes
    |
    = help: try reducing the size of `ArrayError<(i32, T), U>`, for example by boxing large elements or replacing it with `Box<ArrayError<(i32, T), U>>`
 
-error: aborting due to 11 previous errors
+error: aborting due to 12 previous errors
 
diff --git a/src/tools/clippy/tests/ui/seek_from_current.fixed b/src/tools/clippy/tests/ui/seek_from_current.fixed
new file mode 100644
index 00000000000..4b5303324bc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/seek_from_current.fixed
@@ -0,0 +1,26 @@
+// run-rustfix
+#![warn(clippy::seek_from_current)]
+#![feature(custom_inner_attributes)]
+
+use std::fs::File;
+use std::io::{self, Seek, SeekFrom, Write};
+
+fn _msrv_1_50() -> io::Result<()> {
+    #![clippy::msrv = "1.50"]
+    let mut f = File::create("foo.txt")?;
+    f.write_all(b"Hi!")?;
+    f.seek(SeekFrom::Current(0))?;
+    f.seek(SeekFrom::Current(1))?;
+    Ok(())
+}
+
+fn _msrv_1_51() -> io::Result<()> {
+    #![clippy::msrv = "1.51"]
+    let mut f = File::create("foo.txt")?;
+    f.write_all(b"Hi!")?;
+    f.stream_position()?;
+    f.seek(SeekFrom::Current(1))?;
+    Ok(())
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/seek_from_current.rs b/src/tools/clippy/tests/ui/seek_from_current.rs
new file mode 100644
index 00000000000..f93639261a1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/seek_from_current.rs
@@ -0,0 +1,26 @@
+// run-rustfix
+#![warn(clippy::seek_from_current)]
+#![feature(custom_inner_attributes)]
+
+use std::fs::File;
+use std::io::{self, Seek, SeekFrom, Write};
+
+fn _msrv_1_50() -> io::Result<()> {
+    #![clippy::msrv = "1.50"]
+    let mut f = File::create("foo.txt")?;
+    f.write_all(b"Hi!")?;
+    f.seek(SeekFrom::Current(0))?;
+    f.seek(SeekFrom::Current(1))?;
+    Ok(())
+}
+
+fn _msrv_1_51() -> io::Result<()> {
+    #![clippy::msrv = "1.51"]
+    let mut f = File::create("foo.txt")?;
+    f.write_all(b"Hi!")?;
+    f.seek(SeekFrom::Current(0))?;
+    f.seek(SeekFrom::Current(1))?;
+    Ok(())
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/seek_from_current.stderr b/src/tools/clippy/tests/ui/seek_from_current.stderr
new file mode 100644
index 00000000000..db1125b53cd
--- /dev/null
+++ b/src/tools/clippy/tests/ui/seek_from_current.stderr
@@ -0,0 +1,10 @@
+error: using `SeekFrom::Current` to start from current position
+  --> $DIR/seek_from_current.rs:21:5
+   |
+LL |     f.seek(SeekFrom::Current(0))?;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `f.stream_position()`
+   |
+   = note: `-D clippy::seek-from-current` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
new file mode 100644
index 00000000000..464b6cdef63
--- /dev/null
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
@@ -0,0 +1,137 @@
+// run-rustfix
+#![allow(unused)]
+#![feature(custom_inner_attributes)]
+#![warn(clippy::seek_to_start_instead_of_rewind)]
+
+use std::fs::OpenOptions;
+use std::io::{Read, Seek, SeekFrom, Write};
+
+struct StructWithSeekMethod {}
+
+impl StructWithSeekMethod {
+    fn seek(&mut self, from: SeekFrom) {}
+}
+
+trait MySeekTrait {
+    fn seek(&mut self, from: SeekFrom) {}
+}
+
+struct StructWithSeekTrait {}
+impl MySeekTrait for StructWithSeekTrait {}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_method(t: &mut StructWithSeekMethod) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_method_owned_false<T>(mut t: StructWithSeekMethod) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_trait(t: &mut StructWithSeekTrait) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_trait_owned<T>(mut t: StructWithSeekTrait) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_trait_bound<T: MySeekTrait>(t: &mut T) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should trigger clippy warning
+fn seek_to_start<T: Seek>(t: &mut T) {
+    t.rewind();
+}
+
+// This should trigger clippy warning
+fn owned_seek_to_start<T: Seek>(mut t: T) {
+    t.rewind();
+}
+
+// This should NOT trigger clippy warning because
+// it does not seek to start
+fn seek_to_5<T: Seek>(t: &mut T) {
+    t.seek(SeekFrom::Start(5));
+}
+
+// This should NOT trigger clippy warning because
+// it does not seek to start
+fn seek_to_end<T: Seek>(t: &mut T) {
+    t.seek(SeekFrom::End(0));
+}
+
+fn main() {
+    let mut f = OpenOptions::new()
+        .write(true)
+        .read(true)
+        .create(true)
+        .open("foo.txt")
+        .unwrap();
+
+    let mut my_struct_trait = StructWithSeekTrait {};
+    seek_to_start_false_trait_bound(&mut my_struct_trait);
+
+    let hello = "Hello!\n";
+    write!(f, "{hello}").unwrap();
+    seek_to_5(&mut f);
+    seek_to_end(&mut f);
+    seek_to_start(&mut f);
+
+    let mut buf = String::new();
+    f.read_to_string(&mut buf).unwrap();
+
+    assert_eq!(&buf, hello);
+}
+
+fn msrv_1_54() {
+    #![clippy::msrv = "1.54"]
+
+    let mut f = OpenOptions::new()
+        .write(true)
+        .read(true)
+        .create(true)
+        .open("foo.txt")
+        .unwrap();
+
+    let hello = "Hello!\n";
+    write!(f, "{hello}").unwrap();
+
+    f.seek(SeekFrom::Start(0));
+
+    let mut buf = String::new();
+    f.read_to_string(&mut buf).unwrap();
+
+    assert_eq!(&buf, hello);
+}
+
+fn msrv_1_55() {
+    #![clippy::msrv = "1.55"]
+
+    let mut f = OpenOptions::new()
+        .write(true)
+        .read(true)
+        .create(true)
+        .open("foo.txt")
+        .unwrap();
+
+    let hello = "Hello!\n";
+    write!(f, "{hello}").unwrap();
+
+    f.rewind();
+
+    let mut buf = String::new();
+    f.read_to_string(&mut buf).unwrap();
+
+    assert_eq!(&buf, hello);
+}
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
new file mode 100644
index 00000000000..68e09bd7c1f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
@@ -0,0 +1,137 @@
+// run-rustfix
+#![allow(unused)]
+#![feature(custom_inner_attributes)]
+#![warn(clippy::seek_to_start_instead_of_rewind)]
+
+use std::fs::OpenOptions;
+use std::io::{Read, Seek, SeekFrom, Write};
+
+struct StructWithSeekMethod {}
+
+impl StructWithSeekMethod {
+    fn seek(&mut self, from: SeekFrom) {}
+}
+
+trait MySeekTrait {
+    fn seek(&mut self, from: SeekFrom) {}
+}
+
+struct StructWithSeekTrait {}
+impl MySeekTrait for StructWithSeekTrait {}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_method(t: &mut StructWithSeekMethod) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_method_owned_false<T>(mut t: StructWithSeekMethod) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_trait(t: &mut StructWithSeekTrait) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_trait_owned<T>(mut t: StructWithSeekTrait) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_trait_bound<T: MySeekTrait>(t: &mut T) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should trigger clippy warning
+fn seek_to_start<T: Seek>(t: &mut T) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should trigger clippy warning
+fn owned_seek_to_start<T: Seek>(mut t: T) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// it does not seek to start
+fn seek_to_5<T: Seek>(t: &mut T) {
+    t.seek(SeekFrom::Start(5));
+}
+
+// This should NOT trigger clippy warning because
+// it does not seek to start
+fn seek_to_end<T: Seek>(t: &mut T) {
+    t.seek(SeekFrom::End(0));
+}
+
+fn main() {
+    let mut f = OpenOptions::new()
+        .write(true)
+        .read(true)
+        .create(true)
+        .open("foo.txt")
+        .unwrap();
+
+    let mut my_struct_trait = StructWithSeekTrait {};
+    seek_to_start_false_trait_bound(&mut my_struct_trait);
+
+    let hello = "Hello!\n";
+    write!(f, "{hello}").unwrap();
+    seek_to_5(&mut f);
+    seek_to_end(&mut f);
+    seek_to_start(&mut f);
+
+    let mut buf = String::new();
+    f.read_to_string(&mut buf).unwrap();
+
+    assert_eq!(&buf, hello);
+}
+
+fn msrv_1_54() {
+    #![clippy::msrv = "1.54"]
+
+    let mut f = OpenOptions::new()
+        .write(true)
+        .read(true)
+        .create(true)
+        .open("foo.txt")
+        .unwrap();
+
+    let hello = "Hello!\n";
+    write!(f, "{hello}").unwrap();
+
+    f.seek(SeekFrom::Start(0));
+
+    let mut buf = String::new();
+    f.read_to_string(&mut buf).unwrap();
+
+    assert_eq!(&buf, hello);
+}
+
+fn msrv_1_55() {
+    #![clippy::msrv = "1.55"]
+
+    let mut f = OpenOptions::new()
+        .write(true)
+        .read(true)
+        .create(true)
+        .open("foo.txt")
+        .unwrap();
+
+    let hello = "Hello!\n";
+    write!(f, "{hello}").unwrap();
+
+    f.seek(SeekFrom::Start(0));
+
+    let mut buf = String::new();
+    f.read_to_string(&mut buf).unwrap();
+
+    assert_eq!(&buf, hello);
+}
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr
new file mode 100644
index 00000000000..de0eec5d909
--- /dev/null
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr
@@ -0,0 +1,22 @@
+error: used `seek` to go to the start of the stream
+  --> $DIR/seek_to_start_instead_of_rewind.rs:54:7
+   |
+LL |     t.seek(SeekFrom::Start(0));
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()`
+   |
+   = note: `-D clippy::seek-to-start-instead-of-rewind` implied by `-D warnings`
+
+error: used `seek` to go to the start of the stream
+  --> $DIR/seek_to_start_instead_of_rewind.rs:59:7
+   |
+LL |     t.seek(SeekFrom::Start(0));
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()`
+
+error: used `seek` to go to the start of the stream
+  --> $DIR/seek_to_start_instead_of_rewind.rs:131:7
+   |
+LL |     f.seek(SeekFrom::Start(0));
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports.stderr b/src/tools/clippy/tests/ui/single_component_path_imports.stderr
index 509c88ac256..71dcc25d6e5 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports.stderr
+++ b/src/tools/clippy/tests/ui/single_component_path_imports.stderr
@@ -1,16 +1,16 @@
 error: this import is redundant
-  --> $DIR/single_component_path_imports.rs:23:5
+  --> $DIR/single_component_path_imports.rs:5:1
    |
-LL |     use regex;
-   |     ^^^^^^^^^^ help: remove it entirely
+LL | use regex;
+   | ^^^^^^^^^^ help: remove it entirely
    |
    = note: `-D clippy::single-component-path-imports` implied by `-D warnings`
 
 error: this import is redundant
-  --> $DIR/single_component_path_imports.rs:5:1
+  --> $DIR/single_component_path_imports.rs:23:5
    |
-LL | use regex;
-   | ^^^^^^^^^^ help: remove it entirely
+LL |     use regex;
+   |     ^^^^^^^^^^ help: remove it entirely
 
 error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr b/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr
index 633546f6419..330f285202d 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr
+++ b/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr
@@ -1,11 +1,18 @@
 error: this import is redundant
+  --> $DIR/single_component_path_imports_nested_first.rs:4:1
+   |
+LL | use regex;
+   | ^^^^^^^^^^ help: remove it entirely
+   |
+   = note: `-D clippy::single-component-path-imports` implied by `-D warnings`
+
+error: this import is redundant
   --> $DIR/single_component_path_imports_nested_first.rs:13:10
    |
 LL |     use {regex, serde};
    |          ^^^^^
    |
    = help: remove this import
-   = note: `-D clippy::single-component-path-imports` implied by `-D warnings`
 
 error: this import is redundant
   --> $DIR/single_component_path_imports_nested_first.rs:13:17
@@ -15,11 +22,5 @@ LL |     use {regex, serde};
    |
    = help: remove this import
 
-error: this import is redundant
-  --> $DIR/single_component_path_imports_nested_first.rs:4:1
-   |
-LL | use regex;
-   | ^^^^^^^^^^ help: remove it entirely
-
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/string_extend.fixed b/src/tools/clippy/tests/ui/string_extend.fixed
index 1883a9f8325..d200d7310fc 100644
--- a/src/tools/clippy/tests/ui/string_extend.fixed
+++ b/src/tools/clippy/tests/ui/string_extend.fixed
@@ -29,4 +29,7 @@ fn main() {
 
     let f = HasChars;
     s.extend(f.chars());
+
+    // issue #9735
+    s.push_str(&abc[0..2]);
 }
diff --git a/src/tools/clippy/tests/ui/string_extend.rs b/src/tools/clippy/tests/ui/string_extend.rs
index 07d0baa1be6..0dd96a3b210 100644
--- a/src/tools/clippy/tests/ui/string_extend.rs
+++ b/src/tools/clippy/tests/ui/string_extend.rs
@@ -29,4 +29,7 @@ fn main() {
 
     let f = HasChars;
     s.extend(f.chars());
+
+    // issue #9735
+    s.extend(abc[0..2].chars());
 }
diff --git a/src/tools/clippy/tests/ui/string_extend.stderr b/src/tools/clippy/tests/ui/string_extend.stderr
index 6af8c9e1662..b35c77fd961 100644
--- a/src/tools/clippy/tests/ui/string_extend.stderr
+++ b/src/tools/clippy/tests/ui/string_extend.stderr
@@ -18,5 +18,11 @@ error: calling `.extend(_.chars())`
 LL |     s.extend(def.chars());
    |     ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)`
 
-error: aborting due to 3 previous errors
+error: calling `.extend(_.chars())`
+  --> $DIR/string_extend.rs:34:5
+   |
+LL |     s.extend(abc[0..2].chars());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&abc[0..2])`
+
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.rs b/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.rs
new file mode 100644
index 00000000000..eb9fc63fb1d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.rs
@@ -0,0 +1,34 @@
+#![allow(unused)]
+#![warn(clippy::suspicious_xor_used_as_pow)]
+#![allow(clippy::eq_op)]
+
+macro_rules! macro_test {
+    () => {
+        13
+    };
+}
+
+macro_rules! macro_test_inside {
+    () => {
+        1 ^ 2 // should warn even if inside macro
+    };
+}
+
+fn main() {
+    // Should warn:
+    let _ = 2 ^ 5;
+    let _ = 2i32 ^ 9i32;
+    let _ = 2i32 ^ 2i32;
+    let _ = 50i32 ^ 3i32;
+    let _ = 5i32 ^ 8i32;
+    let _ = 2i32 ^ 32i32;
+    macro_test_inside!();
+
+    // Should not warn:
+    let x = 0x02;
+    let _ = x ^ 2;
+    let _ = 2 ^ x;
+    let _ = x ^ 5;
+    let _ = 10 ^ 0b0101;
+    let _ = 2i32 ^ macro_test!();
+}
diff --git a/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr b/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr
new file mode 100644
index 00000000000..8bb3c8fbeeb
--- /dev/null
+++ b/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr
@@ -0,0 +1,51 @@
+error: `^` is not the exponentiation operator
+  --> $DIR/suspicious_xor_used_as_pow.rs:19:13
+   |
+LL |     let _ = 2 ^ 5;
+   |             ^^^^^ help: did you mean to write: `2.pow(5)`
+   |
+   = note: `-D clippy::suspicious-xor-used-as-pow` implied by `-D warnings`
+
+error: `^` is not the exponentiation operator
+  --> $DIR/suspicious_xor_used_as_pow.rs:20:13
+   |
+LL |     let _ = 2i32 ^ 9i32;
+   |             ^^^^^^^^^^^ help: did you mean to write: `2_i32.pow(9_i32)`
+
+error: `^` is not the exponentiation operator
+  --> $DIR/suspicious_xor_used_as_pow.rs:21:13
+   |
+LL |     let _ = 2i32 ^ 2i32;
+   |             ^^^^^^^^^^^ help: did you mean to write: `2_i32.pow(2_i32)`
+
+error: `^` is not the exponentiation operator
+  --> $DIR/suspicious_xor_used_as_pow.rs:22:13
+   |
+LL |     let _ = 50i32 ^ 3i32;
+   |             ^^^^^^^^^^^^ help: did you mean to write: `50_i32.pow(3_i32)`
+
+error: `^` is not the exponentiation operator
+  --> $DIR/suspicious_xor_used_as_pow.rs:23:13
+   |
+LL |     let _ = 5i32 ^ 8i32;
+   |             ^^^^^^^^^^^ help: did you mean to write: `5_i32.pow(8_i32)`
+
+error: `^` is not the exponentiation operator
+  --> $DIR/suspicious_xor_used_as_pow.rs:24:13
+   |
+LL |     let _ = 2i32 ^ 32i32;
+   |             ^^^^^^^^^^^^ help: did you mean to write: `2_i32.pow(32_i32)`
+
+error: `^` is not the exponentiation operator
+  --> $DIR/suspicious_xor_used_as_pow.rs:13:9
+   |
+LL |         1 ^ 2 // should warn even if inside macro
+   |         ^^^^^ help: did you mean to write: `1.pow(2)`
+...
+LL |     macro_test_inside!();
+   |     -------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `macro_test_inside` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/swap.fixed b/src/tools/clippy/tests/ui/swap.fixed
index 24b229235d3..805a2ba5a59 100644
--- a/src/tools/clippy/tests/ui/swap.fixed
+++ b/src/tools/clippy/tests/ui/swap.fixed
@@ -155,3 +155,12 @@ fn issue_8154() {
     let s = S3(&mut s);
     std::mem::swap(&mut s.0.x, &mut s.0.y);
 }
+
+const fn issue_9864(mut u: u32) -> u32 {
+    let mut v = 10;
+
+    let temp = u;
+    u = v;
+    v = temp;
+    u + v
+}
diff --git a/src/tools/clippy/tests/ui/swap.rs b/src/tools/clippy/tests/ui/swap.rs
index a318c27919c..a8c87847952 100644
--- a/src/tools/clippy/tests/ui/swap.rs
+++ b/src/tools/clippy/tests/ui/swap.rs
@@ -179,3 +179,12 @@ fn issue_8154() {
     s.0.x = s.0.y;
     s.0.y = t;
 }
+
+const fn issue_9864(mut u: u32) -> u32 {
+    let mut v = 10;
+
+    let temp = u;
+    u = v;
+    v = temp;
+    u + v
+}
diff --git a/src/tools/clippy/tests/ui/transmute.rs b/src/tools/clippy/tests/ui/transmute.rs
index 001c910239a..1cbacf0feab 100644
--- a/src/tools/clippy/tests/ui/transmute.rs
+++ b/src/tools/clippy/tests/ui/transmute.rs
@@ -1,4 +1,4 @@
-#![allow(dead_code, clippy::borrow_as_ptr)]
+#![allow(dead_code, clippy::borrow_as_ptr, clippy::needless_lifetimes)]
 
 extern crate core;
 
diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
index af4f3b18443..c0af011d33d 100644
--- a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
+++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
@@ -3,6 +3,7 @@
 #![deny(clippy::trivially_copy_pass_by_ref)]
 #![allow(
     clippy::disallowed_names,
+    clippy::needless_lifetimes,
     clippy::redundant_field_names,
     clippy::uninlined_format_args
 )]
diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
index 6a8eca96553..8c5cfa8a0f1 100644
--- a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
+++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
@@ -1,5 +1,5 @@
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:50:11
+  --> $DIR/trivially_copy_pass_by_ref.rs:51:11
    |
 LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
    |           ^^^^ help: consider passing by value instead: `u32`
@@ -11,103 +11,103 @@ LL | #![deny(clippy::trivially_copy_pass_by_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:50:20
+  --> $DIR/trivially_copy_pass_by_ref.rs:51:20
    |
 LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
    |                    ^^^^ help: consider passing by value instead: `Foo`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:50:29
+  --> $DIR/trivially_copy_pass_by_ref.rs:51:29
    |
 LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
    |                             ^^^^ help: consider passing by value instead: `Baz`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:57:12
+  --> $DIR/trivially_copy_pass_by_ref.rs:58:12
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |            ^^^^^ help: consider passing by value instead: `self`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:57:22
+  --> $DIR/trivially_copy_pass_by_ref.rs:58:22
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |                      ^^^^ help: consider passing by value instead: `u32`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:57:31
+  --> $DIR/trivially_copy_pass_by_ref.rs:58:31
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |                               ^^^^ help: consider passing by value instead: `Foo`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:57:40
+  --> $DIR/trivially_copy_pass_by_ref.rs:58:40
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |                                        ^^^^ help: consider passing by value instead: `Baz`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:59:16
+  --> $DIR/trivially_copy_pass_by_ref.rs:60:16
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                ^^^^ help: consider passing by value instead: `u32`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:59:25
+  --> $DIR/trivially_copy_pass_by_ref.rs:60:25
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                         ^^^^ help: consider passing by value instead: `Foo`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:59:34
+  --> $DIR/trivially_copy_pass_by_ref.rs:60:34
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                                  ^^^^ help: consider passing by value instead: `Baz`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:61:35
+  --> $DIR/trivially_copy_pass_by_ref.rs:62:35
    |
 LL |     fn bad_issue7518(self, other: &Self) {}
    |                                   ^^^^^ help: consider passing by value instead: `Self`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:73:16
+  --> $DIR/trivially_copy_pass_by_ref.rs:74:16
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                ^^^^ help: consider passing by value instead: `u32`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:73:25
+  --> $DIR/trivially_copy_pass_by_ref.rs:74:25
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                         ^^^^ help: consider passing by value instead: `Foo`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:73:34
+  --> $DIR/trivially_copy_pass_by_ref.rs:74:34
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                                  ^^^^ help: consider passing by value instead: `Baz`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:77:34
+  --> $DIR/trivially_copy_pass_by_ref.rs:78:34
    |
 LL |     fn trait_method(&self, _foo: &Foo);
    |                                  ^^^^ help: consider passing by value instead: `Foo`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:109:21
+  --> $DIR/trivially_copy_pass_by_ref.rs:110:21
    |
 LL |     fn foo_never(x: &i32) {
    |                     ^^^^ help: consider passing by value instead: `i32`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:114:15
+  --> $DIR/trivially_copy_pass_by_ref.rs:115:15
    |
 LL |     fn foo(x: &i32) {
    |               ^^^^ help: consider passing by value instead: `i32`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:141:37
+  --> $DIR/trivially_copy_pass_by_ref.rs:142:37
    |
 LL | fn _unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 {
    |                                     ^^^^^^^ help: consider passing by value instead: `u32`
diff --git a/src/tools/clippy/tests/ui/unchecked_duration_subtraction.fixed b/src/tools/clippy/tests/ui/unchecked_duration_subtraction.fixed
new file mode 100644
index 00000000000..a0e49a8beb1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unchecked_duration_subtraction.fixed
@@ -0,0 +1,17 @@
+// run-rustfix
+#![warn(clippy::unchecked_duration_subtraction)]
+
+use std::time::{Duration, Instant};
+
+fn main() {
+    let _first = Instant::now();
+    let second = Duration::from_secs(3);
+
+    let _ = _first.checked_sub(second).unwrap();
+
+    let _ = Instant::now().checked_sub(Duration::from_secs(5)).unwrap();
+
+    let _ = _first.checked_sub(Duration::from_secs(5)).unwrap();
+
+    let _ = Instant::now().checked_sub(second).unwrap();
+}
diff --git a/src/tools/clippy/tests/ui/unchecked_duration_subtraction.rs b/src/tools/clippy/tests/ui/unchecked_duration_subtraction.rs
new file mode 100644
index 00000000000..a14a7ea57cc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unchecked_duration_subtraction.rs
@@ -0,0 +1,17 @@
+// run-rustfix
+#![warn(clippy::unchecked_duration_subtraction)]
+
+use std::time::{Duration, Instant};
+
+fn main() {
+    let _first = Instant::now();
+    let second = Duration::from_secs(3);
+
+    let _ = _first - second;
+
+    let _ = Instant::now() - Duration::from_secs(5);
+
+    let _ = _first - Duration::from_secs(5);
+
+    let _ = Instant::now() - second;
+}
diff --git a/src/tools/clippy/tests/ui/unchecked_duration_subtraction.stderr b/src/tools/clippy/tests/ui/unchecked_duration_subtraction.stderr
new file mode 100644
index 00000000000..a2e0aa1d7c0
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unchecked_duration_subtraction.stderr
@@ -0,0 +1,28 @@
+error: unchecked subtraction of a 'Duration' from an 'Instant'
+  --> $DIR/unchecked_duration_subtraction.rs:10:13
+   |
+LL |     let _ = _first - second;
+   |             ^^^^^^^^^^^^^^^ help: try: `_first.checked_sub(second).unwrap()`
+   |
+   = note: `-D clippy::unchecked-duration-subtraction` implied by `-D warnings`
+
+error: unchecked subtraction of a 'Duration' from an 'Instant'
+  --> $DIR/unchecked_duration_subtraction.rs:12:13
+   |
+LL |     let _ = Instant::now() - Duration::from_secs(5);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Instant::now().checked_sub(Duration::from_secs(5)).unwrap()`
+
+error: unchecked subtraction of a 'Duration' from an 'Instant'
+  --> $DIR/unchecked_duration_subtraction.rs:14:13
+   |
+LL |     let _ = _first - Duration::from_secs(5);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `_first.checked_sub(Duration::from_secs(5)).unwrap()`
+
+error: unchecked subtraction of a 'Duration' from an 'Instant'
+  --> $DIR/unchecked_duration_subtraction.rs:16:13
+   |
+LL |     let _ = Instant::now() - second;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Instant::now().checked_sub(second).unwrap()`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs
index 08aee433215..cbc6768033e 100644
--- a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs
@@ -490,4 +490,23 @@ unsafe impl CrateRoot for () {}
 // SAFETY: ok
 unsafe impl CrateRoot for (i32) {}
 
+fn issue_9142() {
+    // SAFETY: ok
+    let _ =
+        // we need this comment to avoid rustfmt putting
+        // it all on one line
+        unsafe {};
+
+    // SAFETY: this is more than one level away, so it should warn
+    let _ = {
+        if unsafe { true } {
+            todo!();
+        } else {
+            let bar = unsafe {};
+            todo!();
+            bar
+        }
+    };
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr
index 2c466ff5c73..ba4de9806d1 100644
--- a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr
+++ b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr
@@ -263,5 +263,29 @@ LL | unsafe impl CrateRoot for () {}
    |
    = help: consider adding a safety comment on the preceding line
 
-error: aborting due to 31 previous errors
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:498:9
+   |
+LL |         unsafe {};
+   |         ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:502:12
+   |
+LL |         if unsafe { true } {
+   |            ^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:505:23
+   |
+LL |             let bar = unsafe {};
+   |                       ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: aborting due to 34 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_join.stderr b/src/tools/clippy/tests/ui/unnecessary_join.stderr
index 0b14b143aff..e919a6d1d8a 100644
--- a/src/tools/clippy/tests/ui/unnecessary_join.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_join.stderr
@@ -1,4 +1,4 @@
-error: called `.collect<Vec<String>>().join("")` on an iterator
+error: called `.collect::<Vec<String>>().join("")` on an iterator
   --> $DIR/unnecessary_join.rs:11:10
    |
 LL |           .collect::<Vec<String>>()
@@ -8,7 +8,7 @@ LL | |         .join("");
    |
    = note: `-D clippy::unnecessary-join` implied by `-D warnings`
 
-error: called `.collect<Vec<String>>().join("")` on an iterator
+error: called `.collect::<Vec<String>>().join("")` on an iterator
   --> $DIR/unnecessary_join.rs:20:10
    |
 LL |           .collect::<Vec<_>>()
diff --git a/src/tools/clippy/tests/ui/unused_rounding.fixed b/src/tools/clippy/tests/ui/unused_rounding.fixed
index 54f85806ac3..38fe6c34cfe 100644
--- a/src/tools/clippy/tests/ui/unused_rounding.fixed
+++ b/src/tools/clippy/tests/ui/unused_rounding.fixed
@@ -6,4 +6,9 @@ fn main() {
     let _ = 1.0f64;
     let _ = 1.00f32;
     let _ = 2e-54f64.floor();
+
+    // issue9866
+    let _ = 3.3_f32.round();
+    let _ = 3.3_f64.round();
+    let _ = 3.0_f32;
 }
diff --git a/src/tools/clippy/tests/ui/unused_rounding.rs b/src/tools/clippy/tests/ui/unused_rounding.rs
index 8d007bc4a1d..a5cac64d023 100644
--- a/src/tools/clippy/tests/ui/unused_rounding.rs
+++ b/src/tools/clippy/tests/ui/unused_rounding.rs
@@ -6,4 +6,9 @@ fn main() {
     let _ = 1.0f64.floor();
     let _ = 1.00f32.round();
     let _ = 2e-54f64.floor();
+
+    // issue9866
+    let _ = 3.3_f32.round();
+    let _ = 3.3_f64.round();
+    let _ = 3.0_f32.round();
 }
diff --git a/src/tools/clippy/tests/ui/unused_rounding.stderr b/src/tools/clippy/tests/ui/unused_rounding.stderr
index 6cfb02e0402..1eeb5d1de88 100644
--- a/src/tools/clippy/tests/ui/unused_rounding.stderr
+++ b/src/tools/clippy/tests/ui/unused_rounding.stderr
@@ -18,5 +18,11 @@ error: used the `round` method with a whole number float
 LL |     let _ = 1.00f32.round();
    |             ^^^^^^^^^^^^^^^ help: remove the `round` method call: `1.00f32`
 
-error: aborting due to 3 previous errors
+error: used the `round` method with a whole number float
+  --> $DIR/unused_rounding.rs:13:13
+   |
+LL |     let _ = 3.0_f32.round();
+   |             ^^^^^^^^^^^^^^^ help: remove the `round` method call: `3.0_f32`
+
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unused_unit.fixed b/src/tools/clippy/tests/ui/unused_unit.fixed
index 7bb43cf7ae8..3dd640b86f0 100644
--- a/src/tools/clippy/tests/ui/unused_unit.fixed
+++ b/src/tools/clippy/tests/ui/unused_unit.fixed
@@ -7,6 +7,7 @@
 // test of the JSON error format.
 
 #![feature(custom_inner_attributes)]
+#![feature(closure_lifetime_binder)]
 #![rustfmt::skip]
 
 #![deny(clippy::unused_unit)]
@@ -87,3 +88,9 @@ fn macro_expr() {
     }
     e!()
 }
+
+mod issue9748 {
+    fn main() {
+        let _ = for<'a> |_: &'a u32| -> () {};
+    }
+}
diff --git a/src/tools/clippy/tests/ui/unused_unit.rs b/src/tools/clippy/tests/ui/unused_unit.rs
index 21073fb802a..bddecf06fb7 100644
--- a/src/tools/clippy/tests/ui/unused_unit.rs
+++ b/src/tools/clippy/tests/ui/unused_unit.rs
@@ -7,6 +7,7 @@
 // test of the JSON error format.
 
 #![feature(custom_inner_attributes)]
+#![feature(closure_lifetime_binder)]
 #![rustfmt::skip]
 
 #![deny(clippy::unused_unit)]
@@ -87,3 +88,9 @@ fn macro_expr() {
     }
     e!()
 }
+
+mod issue9748 {
+    fn main() {
+        let _ = for<'a> |_: &'a u32| -> () {};
+    }
+}
diff --git a/src/tools/clippy/tests/ui/unused_unit.stderr b/src/tools/clippy/tests/ui/unused_unit.stderr
index 0d2cb77855b..ce06738cfe4 100644
--- a/src/tools/clippy/tests/ui/unused_unit.stderr
+++ b/src/tools/clippy/tests/ui/unused_unit.stderr
@@ -1,119 +1,119 @@
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:19:58
+  --> $DIR/unused_unit.rs:20:58
    |
 LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
    |                                                          ^^^^^^ help: remove the `-> ()`
    |
 note: the lint level is defined here
-  --> $DIR/unused_unit.rs:12:9
+  --> $DIR/unused_unit.rs:13:9
    |
 LL | #![deny(clippy::unused_unit)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:19:28
+  --> $DIR/unused_unit.rs:20:28
    |
 LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
    |                            ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:20:18
+  --> $DIR/unused_unit.rs:21:18
    |
 LL |     where G: Fn() -> () {
    |                  ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:21:26
+  --> $DIR/unused_unit.rs:22:26
    |
 LL |         let _y: &dyn Fn() -> () = &f;
    |                          ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:28:18
+  --> $DIR/unused_unit.rs:29:18
    |
 LL |     fn into(self) -> () {
    |                  ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit expression
-  --> $DIR/unused_unit.rs:29:9
+  --> $DIR/unused_unit.rs:30:9
    |
 LL |         ()
    |         ^^ help: remove the final `()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:34:29
+  --> $DIR/unused_unit.rs:35:29
    |
 LL |     fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H)
    |                             ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:36:19
+  --> $DIR/unused_unit.rs:37:19
    |
 LL |         G: FnMut() -> (),
    |                   ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:37:16
+  --> $DIR/unused_unit.rs:38:16
    |
 LL |         H: Fn() -> ();
    |                ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:41:29
+  --> $DIR/unused_unit.rs:42:29
    |
 LL |     fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H)
    |                             ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:43:19
+  --> $DIR/unused_unit.rs:44:19
    |
 LL |         G: FnMut() -> (),
    |                   ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:44:16
+  --> $DIR/unused_unit.rs:45:16
    |
 LL |         H: Fn() -> () {}
    |                ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:47:17
+  --> $DIR/unused_unit.rs:48:17
    |
 LL | fn return_unit() -> () { () }
    |                 ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit expression
-  --> $DIR/unused_unit.rs:47:26
+  --> $DIR/unused_unit.rs:48:26
    |
 LL | fn return_unit() -> () { () }
    |                          ^^ help: remove the final `()`
 
 error: unneeded `()`
-  --> $DIR/unused_unit.rs:57:14
+  --> $DIR/unused_unit.rs:58:14
    |
 LL |         break();
    |              ^^ help: remove the `()`
 
 error: unneeded `()`
-  --> $DIR/unused_unit.rs:59:11
+  --> $DIR/unused_unit.rs:60:11
    |
 LL |     return();
    |           ^^ help: remove the `()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:76:10
+  --> $DIR/unused_unit.rs:77:10
    |
 LL | fn test()->(){}
    |          ^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:79:11
+  --> $DIR/unused_unit.rs:80:11
    |
 LL | fn test2() ->(){}
    |           ^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:82:11
+  --> $DIR/unused_unit.rs:83:11
    |
 LL | fn test3()-> (){}
    |           ^^^^^ help: remove the `-> ()`
diff --git a/src/tools/clippy/tests/ui/unwrap.stderr b/src/tools/clippy/tests/ui/unwrap.stderr
index e88d580f7bd..d49bf2b3228 100644
--- a/src/tools/clippy/tests/ui/unwrap.stderr
+++ b/src/tools/clippy/tests/ui/unwrap.stderr
@@ -1,4 +1,4 @@
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap.rs:5:13
    |
 LL |     let _ = opt.unwrap();
@@ -7,7 +7,7 @@ LL |     let _ = opt.unwrap();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
-error: used `unwrap()` on `a Result` value
+error: used `unwrap()` on a `Result` value
   --> $DIR/unwrap.rs:10:13
    |
 LL |     let _ = res.unwrap();
@@ -15,7 +15,7 @@ LL |     let _ = res.unwrap();
    |
    = help: if you don't want to handle the `Err` case gracefully, consider using `expect()` to provide a better panic message
 
-error: used `unwrap_err()` on `a Result` value
+error: used `unwrap_err()` on a `Result` value
   --> $DIR/unwrap.rs:11:13
    |
 LL |     let _ = res.unwrap_err();
diff --git a/src/tools/clippy/tests/ui/unwrap_expect_used.stderr b/src/tools/clippy/tests/ui/unwrap_expect_used.stderr
index 211d2be1834..fe4ecef1145 100644
--- a/src/tools/clippy/tests/ui/unwrap_expect_used.stderr
+++ b/src/tools/clippy/tests/ui/unwrap_expect_used.stderr
@@ -1,4 +1,4 @@
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_expect_used.rs:23:5
    |
 LL |     Some(3).unwrap();
@@ -7,7 +7,7 @@ LL |     Some(3).unwrap();
    = help: if this value is `None`, it will panic
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
-error: used `expect()` on `an Option` value
+error: used `expect()` on an `Option` value
   --> $DIR/unwrap_expect_used.rs:24:5
    |
 LL |     Some(3).expect("Hello world!");
@@ -16,7 +16,7 @@ LL |     Some(3).expect("Hello world!");
    = help: if this value is `None`, it will panic
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
-error: used `unwrap()` on `a Result` value
+error: used `unwrap()` on a `Result` value
   --> $DIR/unwrap_expect_used.rs:31:5
    |
 LL |     a.unwrap();
@@ -24,7 +24,7 @@ LL |     a.unwrap();
    |
    = help: if this value is an `Err`, it will panic
 
-error: used `expect()` on `a Result` value
+error: used `expect()` on a `Result` value
   --> $DIR/unwrap_expect_used.rs:32:5
    |
 LL |     a.expect("Hello world!");
@@ -32,7 +32,7 @@ LL |     a.expect("Hello world!");
    |
    = help: if this value is an `Err`, it will panic
 
-error: used `unwrap_err()` on `a Result` value
+error: used `unwrap_err()` on a `Result` value
   --> $DIR/unwrap_expect_used.rs:33:5
    |
 LL |     a.unwrap_err();
@@ -40,7 +40,7 @@ LL |     a.unwrap_err();
    |
    = help: if this value is an `Ok`, it will panic
 
-error: used `expect_err()` on `a Result` value
+error: used `expect_err()` on a `Result` value
   --> $DIR/unwrap_expect_used.rs:34:5
    |
 LL |     a.expect_err("Hello error!");
diff --git a/src/tools/clippy/tests/ui/unwrap_or.rs b/src/tools/clippy/tests/ui/unwrap_or.rs
index bfb41e43947..a0c003f5b1e 100644
--- a/src/tools/clippy/tests/ui/unwrap_or.rs
+++ b/src/tools/clippy/tests/ui/unwrap_or.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::all)]
+#![warn(clippy::all, clippy::or_fun_call)]
 
 fn main() {
     let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len();
diff --git a/src/tools/clippy/tests/ui/use_self_trait.fixed b/src/tools/clippy/tests/ui/use_self_trait.fixed
index 9bcd692fb35..4e779308d02 100644
--- a/src/tools/clippy/tests/ui/use_self_trait.fixed
+++ b/src/tools/clippy/tests/ui/use_self_trait.fixed
@@ -47,8 +47,7 @@ impl Mul for Bad {
 
 impl Clone for Bad {
     fn clone(&self) -> Self {
-        // FIXME: applicable here
-        Bad
+        Self
     }
 }
 
@@ -112,4 +111,42 @@ impl NameTrait for u8 {
     }
 }
 
+mod impl_in_macro {
+    macro_rules! parse_ip_impl {
+        // minimized from serde=1.0.118
+        ($ty:ty) => {
+            impl FooTrait for $ty {
+                fn new() -> Self {
+                    <$ty>::bar()
+                }
+            }
+        };
+    }
+
+    struct Foo;
+
+    trait FooTrait {
+        fn new() -> Self;
+    }
+
+    impl Foo {
+        fn bar() -> Self {
+            Self
+        }
+    }
+    parse_ip_impl!(Foo); // Should not lint
+}
+
+mod full_path_replacement {
+    trait Error {
+        fn custom<T: std::fmt::Display>(_msg: T) -> Self;
+    }
+
+    impl Error for std::fmt::Error {
+        fn custom<T: std::fmt::Display>(_msg: T) -> Self {
+            Self // Should lint
+        }
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/use_self_trait.rs b/src/tools/clippy/tests/ui/use_self_trait.rs
index de305d40f33..325dc73b21e 100644
--- a/src/tools/clippy/tests/ui/use_self_trait.rs
+++ b/src/tools/clippy/tests/ui/use_self_trait.rs
@@ -47,7 +47,6 @@ impl Mul for Bad {
 
 impl Clone for Bad {
     fn clone(&self) -> Self {
-        // FIXME: applicable here
         Bad
     }
 }
@@ -112,4 +111,42 @@ impl NameTrait for u8 {
     }
 }
 
+mod impl_in_macro {
+    macro_rules! parse_ip_impl {
+        // minimized from serde=1.0.118
+        ($ty:ty) => {
+            impl FooTrait for $ty {
+                fn new() -> Self {
+                    <$ty>::bar()
+                }
+            }
+        };
+    }
+
+    struct Foo;
+
+    trait FooTrait {
+        fn new() -> Self;
+    }
+
+    impl Foo {
+        fn bar() -> Self {
+            Self
+        }
+    }
+    parse_ip_impl!(Foo); // Should not lint
+}
+
+mod full_path_replacement {
+    trait Error {
+        fn custom<T: std::fmt::Display>(_msg: T) -> Self;
+    }
+
+    impl Error for std::fmt::Error {
+        fn custom<T: std::fmt::Display>(_msg: T) -> Self {
+            std::fmt::Error // Should lint
+        }
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/use_self_trait.stderr b/src/tools/clippy/tests/ui/use_self_trait.stderr
index 55af3ff2a93..090729b9c3d 100644
--- a/src/tools/clippy/tests/ui/use_self_trait.stderr
+++ b/src/tools/clippy/tests/ui/use_self_trait.stderr
@@ -84,5 +84,17 @@ error: unnecessary structure name repetition
 LL |     fn mul(self, rhs: Bad) -> Bad {
    |                               ^^^ help: use the applicable keyword: `Self`
 
-error: aborting due to 14 previous errors
+error: unnecessary structure name repetition
+  --> $DIR/use_self_trait.rs:50:9
+   |
+LL |         Bad
+   |         ^^^ help: use the applicable keyword: `Self`
+
+error: unnecessary structure name repetition
+  --> $DIR/use_self_trait.rs:147:13
+   |
+LL |             std::fmt::Error // Should lint
+   |             ^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
+
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/useless_attribute.fixed b/src/tools/clippy/tests/ui/useless_attribute.fixed
index c23231a99e9..871e4fb5c3a 100644
--- a/src/tools/clippy/tests/ui/useless_attribute.fixed
+++ b/src/tools/clippy/tests/ui/useless_attribute.fixed
@@ -1,6 +1,7 @@
 // run-rustfix
 // aux-build:proc_macro_derive.rs
 
+#![allow(unused)]
 #![warn(clippy::useless_attribute)]
 #![warn(unreachable_pub)]
 #![feature(rustc_private)]
@@ -16,6 +17,13 @@ extern crate rustc_middle;
 #[macro_use]
 extern crate proc_macro_derive;
 
+fn test_indented_attr() {
+    #![allow(clippy::almost_swapped)]
+    use std::collections::HashSet;
+
+    let _ = HashSet::<u32>::default();
+}
+
 // don't lint on unused_import for `use` items
 #[allow(unused_imports)]
 use std::collections;
@@ -63,13 +71,16 @@ mod c {
     pub(crate) struct S;
 }
 
-fn test_indented_attr() {
-    #![allow(clippy::almost_swapped)]
-    use std::collections::HashSet;
-
-    let _ = HashSet::<u32>::default();
+// https://github.com/rust-lang/rust-clippy/issues/7511
+pub mod split {
+    #[allow(clippy::module_name_repetitions)]
+    pub use regex::SplitN;
 }
 
+// https://github.com/rust-lang/rust-clippy/issues/8768
+#[allow(clippy::single_component_path_imports)]
+use regex;
+
 fn main() {
     test_indented_attr();
 }
diff --git a/src/tools/clippy/tests/ui/useless_attribute.rs b/src/tools/clippy/tests/ui/useless_attribute.rs
index 7a7b198ea60..cb50736ba39 100644
--- a/src/tools/clippy/tests/ui/useless_attribute.rs
+++ b/src/tools/clippy/tests/ui/useless_attribute.rs
@@ -1,6 +1,7 @@
 // run-rustfix
 // aux-build:proc_macro_derive.rs
 
+#![allow(unused)]
 #![warn(clippy::useless_attribute)]
 #![warn(unreachable_pub)]
 #![feature(rustc_private)]
@@ -16,6 +17,13 @@ extern crate rustc_middle;
 #[macro_use]
 extern crate proc_macro_derive;
 
+fn test_indented_attr() {
+    #[allow(clippy::almost_swapped)]
+    use std::collections::HashSet;
+
+    let _ = HashSet::<u32>::default();
+}
+
 // don't lint on unused_import for `use` items
 #[allow(unused_imports)]
 use std::collections;
@@ -63,13 +71,16 @@ mod c {
     pub(crate) struct S;
 }
 
-fn test_indented_attr() {
-    #[allow(clippy::almost_swapped)]
-    use std::collections::HashSet;
-
-    let _ = HashSet::<u32>::default();
+// https://github.com/rust-lang/rust-clippy/issues/7511
+pub mod split {
+    #[allow(clippy::module_name_repetitions)]
+    pub use regex::SplitN;
 }
 
+// https://github.com/rust-lang/rust-clippy/issues/8768
+#[allow(clippy::single_component_path_imports)]
+use regex;
+
 fn main() {
     test_indented_attr();
 }
diff --git a/src/tools/clippy/tests/ui/useless_attribute.stderr b/src/tools/clippy/tests/ui/useless_attribute.stderr
index 255d2876355..a7ea0df2294 100644
--- a/src/tools/clippy/tests/ui/useless_attribute.stderr
+++ b/src/tools/clippy/tests/ui/useless_attribute.stderr
@@ -1,5 +1,5 @@
 error: useless lint attribute
-  --> $DIR/useless_attribute.rs:8:1
+  --> $DIR/useless_attribute.rs:9:1
    |
 LL | #[allow(dead_code)]
    | ^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(dead_code)]`
@@ -7,13 +7,13 @@ LL | #[allow(dead_code)]
    = note: `-D clippy::useless-attribute` implied by `-D warnings`
 
 error: useless lint attribute
-  --> $DIR/useless_attribute.rs:9:1
+  --> $DIR/useless_attribute.rs:10:1
    |
 LL | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code)`
 
 error: useless lint attribute
-  --> $DIR/useless_attribute.rs:67:5
+  --> $DIR/useless_attribute.rs:21:5
    |
 LL |     #[allow(clippy::almost_swapped)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(clippy::almost_swapped)]`
diff --git a/src/tools/clippy/tests/versioncheck.rs b/src/tools/clippy/tests/versioncheck.rs
index a6d8d0307ce..7a85386a3df 100644
--- a/src/tools/clippy/tests/versioncheck.rs
+++ b/src/tools/clippy/tests/versioncheck.rs
@@ -6,7 +6,7 @@ use rustc_tools_util::VersionInfo;
 use std::fs;
 
 #[test]
-fn check_that_clippy_lints_and_clippy_utils_have_the_same_version_as_clippy() {
+fn consistent_clippy_crate_versions() {
     fn read_version(path: &str) -> String {
         let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("error reading `{path}`: {e:?}"));
         contents
@@ -24,11 +24,16 @@ fn check_that_clippy_lints_and_clippy_utils_have_the_same_version_as_clippy() {
     }
 
     let clippy_version = read_version("Cargo.toml");
-    let clippy_lints_version = read_version("clippy_lints/Cargo.toml");
-    let clippy_utils_version = read_version("clippy_utils/Cargo.toml");
 
-    assert_eq!(clippy_version, clippy_lints_version);
-    assert_eq!(clippy_version, clippy_utils_version);
+    let paths = [
+        "declare_clippy_lint/Cargo.toml",
+        "clippy_lints/Cargo.toml",
+        "clippy_utils/Cargo.toml",
+    ];
+
+    for path in paths {
+        assert_eq!(clippy_version, read_version(path), "{path} version differs");
+    }
 }
 
 #[test]
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 8931c17bbdc..41c5d36671d 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -222,6 +222,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "command-group"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7a8a86f409b4a59df3a3e4bee2de0b83f1755fdd2a25e3a9684c396fc4bed2c"
+dependencies = [
+ "nix",
+ "winapi",
+]
+
+[[package]]
 name = "countme"
 version = "3.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -300,7 +310,7 @@ dependencies = [
  "hashbrown",
  "lock_api",
  "once_cell",
- "parking_lot_core 0.9.3",
+ "parking_lot_core 0.9.4",
 ]
 
 [[package]]
@@ -359,14 +369,14 @@ dependencies = [
 
 [[package]]
 name = "filetime"
-version = "0.2.17"
+version = "0.2.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e94a7bbaa59354bc20dd75b67f23e2797b4490e9d6928203fb105c79e448c86c"
+checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3"
 dependencies = [
  "cfg-if",
  "libc",
  "redox_syscall",
- "windows-sys 0.36.1",
+ "windows-sys 0.42.0",
 ]
 
 [[package]]
@@ -390,6 +400,7 @@ name = "flycheck"
 version = "0.0.0"
 dependencies = [
  "cargo_metadata",
+ "command-group",
  "crossbeam-channel",
  "jod-thread",
  "paths",
@@ -963,11 +974,24 @@ dependencies = [
 
 [[package]]
 name = "miow"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7377f7792b3afb6a3cba68daa54ca23c032137010460d667fda53a8d66be00e"
+checksum = "52ffbca2f655e33c08be35d87278e5b18b89550a37dbd598c20db92f6a471123"
 dependencies = [
- "windows-sys 0.28.0",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "nix"
+version = "0.22.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf"
+dependencies = [
+ "bitflags",
+ "cc",
+ "cfg-if",
+ "libc",
+ "memoffset",
 ]
 
 [[package]]
@@ -1037,7 +1061,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
 dependencies = [
  "lock_api",
- "parking_lot_core 0.9.3",
+ "parking_lot_core 0.9.4",
 ]
 
 [[package]]
@@ -1056,15 +1080,15 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.3"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
+checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
 dependencies = [
  "cfg-if",
  "libc",
  "redox_syscall",
  "smallvec",
- "windows-sys 0.36.1",
+ "windows-sys 0.42.0",
 ]
 
 [[package]]
@@ -1981,19 +2005,6 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
 name = "windows-sys"
-version = "0.28.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82ca39602d5cbfa692c4b67e3bcbb2751477355141c1ed434c94da4186836ff6"
-dependencies = [
- "windows_aarch64_msvc 0.28.0",
- "windows_i686_gnu 0.28.0",
- "windows_i686_msvc 0.28.0",
- "windows_x86_64_gnu 0.28.0",
- "windows_x86_64_msvc 0.28.0",
-]
-
-[[package]]
-name = "windows-sys"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
@@ -2006,10 +2017,25 @@ dependencies = [
 ]
 
 [[package]]
-name = "windows_aarch64_msvc"
-version = "0.28.0"
+name = "windows-sys"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc 0.42.0",
+ "windows_i686_gnu 0.42.0",
+ "windows_i686_msvc 0.42.0",
+ "windows_x86_64_gnu 0.42.0",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc 0.42.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2"
+checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
 
 [[package]]
 name = "windows_aarch64_msvc"
@@ -2018,10 +2044,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
 
 [[package]]
-name = "windows_i686_gnu"
-version = "0.28.0"
+name = "windows_aarch64_msvc"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a"
+checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
 
 [[package]]
 name = "windows_i686_gnu"
@@ -2030,10 +2056,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
 
 [[package]]
-name = "windows_i686_msvc"
-version = "0.28.0"
+name = "windows_i686_gnu"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64"
+checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
 
 [[package]]
 name = "windows_i686_msvc"
@@ -2042,10 +2068,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
 
 [[package]]
-name = "windows_x86_64_gnu"
-version = "0.28.0"
+name = "windows_i686_msvc"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954"
+checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
 
 [[package]]
 name = "windows_x86_64_gnu"
@@ -2054,10 +2080,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
 
 [[package]]
-name = "windows_x86_64_msvc"
-version = "0.28.0"
+name = "windows_x86_64_gnu"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f"
+checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
 
 [[package]]
 name = "windows_x86_64_msvc"
@@ -2066,6 +2098,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
 
 [[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
+
+[[package]]
 name = "write-json"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/tools/rust-analyzer/crates/base-db/Cargo.toml b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
index f02a51ab6c4..a484ecec682 100644
--- a/src/tools/rust-analyzer/crates/base-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/cfg/Cargo.toml b/src/tools/rust-analyzer/crates/cfg/Cargo.toml
index ee1ad677a95..2857420c285 100644
--- a/src/tools/rust-analyzer/crates/cfg/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/cfg/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/flycheck/Cargo.toml b/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
index 2ad32d24837..514d567fcce 100644
--- a/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
@@ -17,6 +17,7 @@ rustc-hash = "1.1.0"
 serde = { version = "1.0.137", features = ["derive"] }
 serde_json = "1.0.86"
 jod-thread = "0.1.2"
+command-group = "1.0.8"
 
 toolchain = { path = "../toolchain", version = "0.0.0" }
 stdx = { path = "../stdx", version = "0.0.0" }
diff --git a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
index ac086d4fe74..8f93dad06e3 100644
--- a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
@@ -10,11 +10,12 @@ use std::{
     time::Duration,
 };
 
+use command_group::{CommandGroup, GroupChild};
 use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
 use paths::AbsPathBuf;
 use rustc_hash::FxHashMap;
 use serde::Deserialize;
-use stdx::{process::streaming_output, JodChild};
+use stdx::process::streaming_output;
 
 pub use cargo_metadata::diagnostic::{
     Applicability, Diagnostic, DiagnosticCode, DiagnosticLevel, DiagnosticSpan,
@@ -39,7 +40,7 @@ pub enum InvocationLocation {
 pub enum FlycheckConfig {
     CargoCommand {
         command: String,
-        target_triple: Option<String>,
+        target_triples: Vec<String>,
         all_targets: bool,
         no_default_features: bool,
         all_features: bool,
@@ -285,7 +286,7 @@ impl FlycheckActor {
         let (mut cmd, args) = match &self.config {
             FlycheckConfig::CargoCommand {
                 command,
-                target_triple,
+                target_triples,
                 no_default_features,
                 all_targets,
                 all_features,
@@ -299,7 +300,7 @@ impl FlycheckActor {
                 cmd.args(&["--workspace", "--message-format=json", "--manifest-path"])
                     .arg(self.root.join("Cargo.toml").as_os_str());
 
-                if let Some(target) = target_triple {
+                for target in target_triples {
                     cmd.args(&["--target", target.as_str()]);
                 }
                 if *all_targets {
@@ -359,6 +360,8 @@ impl FlycheckActor {
     }
 }
 
+struct JodChild(GroupChild);
+
 /// A handle to a cargo process used for fly-checking.
 struct CargoHandle {
     /// The handle to the actual cargo process. As we cannot cancel directly from with
@@ -371,10 +374,10 @@ struct CargoHandle {
 impl CargoHandle {
     fn spawn(mut command: Command) -> std::io::Result<CargoHandle> {
         command.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null());
-        let mut child = JodChild::spawn(command)?;
+        let mut child = command.group_spawn().map(JodChild)?;
 
-        let stdout = child.stdout.take().unwrap();
-        let stderr = child.stderr.take().unwrap();
+        let stdout = child.0.inner().stdout.take().unwrap();
+        let stderr = child.0.inner().stderr.take().unwrap();
 
         let (sender, receiver) = unbounded();
         let actor = CargoActor::new(sender, stdout, stderr);
@@ -386,13 +389,13 @@ impl CargoHandle {
     }
 
     fn cancel(mut self) {
-        let _ = self.child.kill();
-        let _ = self.child.wait();
+        let _ = self.child.0.kill();
+        let _ = self.child.0.wait();
     }
 
     fn join(mut self) -> io::Result<()> {
-        let _ = self.child.kill();
-        let exit_status = self.child.wait()?;
+        let _ = self.child.0.kill();
+        let exit_status = self.child.0.wait()?;
         let (read_at_least_one_message, error) = self.thread.join()?;
         if read_at_least_one_message || exit_status.success() {
             Ok(())
diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
index 4ad8e75970b..22f98ea7cd4 100644
--- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index 2dc69b00ace..9c769690864 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -236,11 +236,19 @@ impl TraitData {
             .by_key("rustc_skip_array_during_method_dispatch")
             .exists();
 
-        let mut collector =
-            AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
-        collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
-        let (items, attribute_calls, diagnostics) = collector.finish();
-
+        let (items, attribute_calls, diagnostics) = match &tr_def.items {
+            Some(items) => {
+                let mut collector = AssocItemCollector::new(
+                    db,
+                    module_id,
+                    tree_id.file_id(),
+                    ItemContainerId::TraitId(tr),
+                );
+                collector.collect(&item_tree, tree_id.tree_id(), items);
+                collector.finish()
+            }
+            None => Default::default(),
+        };
         (
             Arc::new(TraitData {
                 name,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
index 570344596de..0aa531eff71 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
@@ -666,7 +666,8 @@ pub struct Trait {
     pub generic_params: Interned<GenericParams>,
     pub is_auto: bool,
     pub is_unsafe: bool,
-    pub items: Box<[AssocItem]>,
+    /// This is [`None`] if this Trait is a trait alias.
+    pub items: Option<Box<[AssocItem]>>,
     pub ast_id: FileAstId<ast::Trait>,
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
index 79249757d9e..b25274bccc9 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
@@ -451,15 +451,7 @@ impl<'a> Ctx<'a> {
                 .collect()
         });
         let ast_id = self.source_ast_id_map.ast_id(trait_def);
-        let res = Trait {
-            name,
-            visibility,
-            generic_params,
-            is_auto,
-            is_unsafe,
-            items: items.unwrap_or_default(),
-            ast_id,
-        };
+        let res = Trait { name, visibility, generic_params, is_auto, is_unsafe, items, ast_id };
         Some(id(self.data().traits.alloc(res)))
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
index da1643152c2..48c40df22ff 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
@@ -375,12 +375,21 @@ impl<'a> Printer<'a> {
                 }
                 w!(self, "trait {}", name);
                 self.print_generic_params(generic_params);
-                self.print_where_clause_and_opening_brace(generic_params);
-                self.indented(|this| {
-                    for item in &**items {
-                        this.print_mod_item((*item).into());
+                match items {
+                    Some(items) => {
+                        self.print_where_clause_and_opening_brace(generic_params);
+                        self.indented(|this| {
+                            for item in &**items {
+                                this.print_mod_item((*item).into());
+                            }
+                        });
                     }
-                });
+                    None => {
+                        w!(self, " = ");
+                        // FIXME: Print the aliased traits
+                        self.print_where_clause_and_opening_brace(generic_params);
+                    }
+                }
                 wln!(self, "}}");
             }
             ModItem::Impl(it) => {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
index bc162d0fa20..fc90c6e9f37 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
@@ -94,11 +94,11 @@ macro_rules! m {
     ($($s:stmt)*) => (stringify!($($s |)*);)
 }
 stringify!(;
-|;
-|92|;
-|let x = 92|;
+| ;
+|92| ;
+|let x = 92| ;
 |loop {}
-|;
+| ;
 |);
 "#]],
     );
@@ -118,7 +118,7 @@ m!(.. .. ..);
 macro_rules! m {
     ($($p:pat)*) => (stringify!($($p |)*);)
 }
-stringify!(.. .. ..|);
+stringify!(.. .. .. |);
 "#]],
     );
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs
index 029821e5e87..118c14ed843 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs
@@ -82,14 +82,14 @@ fn attribute_macro_syntax_completion_2() {
 #[proc_macros::identity_when_valid]
 fn foo() { bar.; blub }
 "#,
-        expect![[r##"
+        expect![[r#"
 #[proc_macros::identity_when_valid]
 fn foo() { bar.; blub }
 
 fn foo() {
-    bar.;
+    bar. ;
     blub
-}"##]],
+}"#]],
     );
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index 9ffc218818c..b0dd01f9dbe 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -212,6 +212,7 @@ impl Import {
 
 #[derive(Debug, Eq, PartialEq)]
 struct ImportDirective {
+    /// The module this import directive is in.
     module_id: LocalModuleId,
     import: Import,
     status: PartialResolvedImport,
@@ -963,8 +964,10 @@ impl DefCollector<'_> {
 
     fn update(
         &mut self,
+        // The module for which `resolutions` have been resolve
         module_id: LocalModuleId,
         resolutions: &[(Option<Name>, PerNs)],
+        // Visibility this import will have
         vis: Visibility,
         import_type: ImportType,
     ) {
@@ -974,6 +977,7 @@ impl DefCollector<'_> {
 
     fn update_recursive(
         &mut self,
+        // The module for which `resolutions` have been resolve
         module_id: LocalModuleId,
         resolutions: &[(Option<Name>, PerNs)],
         // All resolutions are imported with this visibility; the visibilities in
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
index 8dfda6df64e..20d39ec6cb9 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
@@ -73,7 +73,10 @@ impl DefMap {
     pub(crate) fn resolve_visibility(
         &self,
         db: &dyn DefDatabase,
+        // module to import to
         original_module: LocalModuleId,
+        // pub(path)
+        //     ^^^^ this
         visibility: &RawVisibility,
     ) -> Option<Visibility> {
         let mut vis = match visibility {
@@ -115,6 +118,7 @@ impl DefMap {
         &self,
         db: &dyn DefDatabase,
         mode: ResolveMode,
+        // module to import to
         mut original_module: LocalModuleId,
         path: &ModPath,
         shadow: BuiltinShadowMode,
@@ -361,6 +365,9 @@ impl DefMap {
                     );
                 }
             };
+
+            curr_per_ns = curr_per_ns
+                .filter_visibility(|vis| vis.is_visible_from_def_map(db, self, original_module));
         }
 
         ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None, Some(self.krate))
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
index 70dd2eb3ade..0d90047c28f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
@@ -58,9 +58,9 @@ extern {
 "#,
         expect![[r#"
             crate
-            E: t
+            E: _
             S: t v
-            V: t v
+            V: _
             foo: t
 
             crate::foo
@@ -307,7 +307,7 @@ pub struct FromLib;
             Bar: t v
 
             crate::foo
-            Bar: t v
+            Bar: _
             FromLib: t v
         "#]],
     );
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
index b2a6a592cf3..88a3c76393f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
@@ -119,7 +119,7 @@ use foo::*;
 use foo::bar::*;
 
 //- /foo/mod.rs
-mod bar;
+pub mod bar;
 fn Foo() {};
 pub struct Foo {};
 
@@ -132,6 +132,7 @@ pub(crate) struct PubCrateStruct;
             crate
             Foo: t
             PubCrateStruct: t v
+            bar: t
             foo: t
 
             crate::foo
@@ -336,3 +337,33 @@ mod d {
         "#]],
     );
 }
+
+#[test]
+fn glob_name_collision_check_visibility() {
+    check(
+        r#"
+mod event {
+    mod serenity {
+        pub fn Event() {}
+    }
+    use serenity::*;
+
+    pub struct Event {}
+}
+
+use event::Event;
+        "#,
+        expect![[r#"
+            crate
+            Event: t
+            event: t
+
+            crate::event
+            Event: t v
+            serenity: t
+
+            crate::event::serenity
+            Event: v
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs
index ba3bf8b5a5c..c575bf7cac2 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs
@@ -580,7 +580,7 @@ fn module_resolution_decl_inside_inline_module_in_crate_root() {
 //- /main.rs
 mod foo {
     #[path = "baz.rs"]
-    mod bar;
+    pub mod bar;
 }
 use self::foo::bar::Baz;
 
diff --git a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
index 3359c99b396..77eb1fd4504 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs
index 893e6fe4b82..a4abe75626e 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs
@@ -4,6 +4,7 @@ use std::mem;
 
 use mbe::{SyntheticToken, SyntheticTokenId, TokenMap};
 use rustc_hash::FxHashMap;
+use smallvec::SmallVec;
 use syntax::{
     ast::{self, AstNode, HasLoopBody},
     match_ast, SyntaxElement, SyntaxKind, SyntaxNode, TextRange,
@@ -292,25 +293,34 @@ pub(crate) fn reverse_fixups(
     token_map: &TokenMap,
     undo_info: &SyntaxFixupUndoInfo,
 ) {
-    tt.token_trees.retain(|tt| match tt {
-        tt::TokenTree::Leaf(leaf) => {
-            token_map.synthetic_token_id(leaf.id()).is_none()
-                || token_map.synthetic_token_id(leaf.id()) != Some(EMPTY_ID)
-        }
-        tt::TokenTree::Subtree(st) => st.delimiter.map_or(true, |d| {
-            token_map.synthetic_token_id(d.id).is_none()
-                || token_map.synthetic_token_id(d.id) != Some(EMPTY_ID)
-        }),
-    });
-    tt.token_trees.iter_mut().for_each(|tt| match tt {
-        tt::TokenTree::Subtree(tt) => reverse_fixups(tt, token_map, undo_info),
-        tt::TokenTree::Leaf(leaf) => {
-            if let Some(id) = token_map.synthetic_token_id(leaf.id()) {
-                let original = &undo_info.original[id.0 as usize];
-                *tt = tt::TokenTree::Subtree(original.clone());
+    let tts = std::mem::take(&mut tt.token_trees);
+    tt.token_trees = tts
+        .into_iter()
+        .filter(|tt| match tt {
+            tt::TokenTree::Leaf(leaf) => token_map.synthetic_token_id(leaf.id()) != Some(EMPTY_ID),
+            tt::TokenTree::Subtree(st) => {
+                st.delimiter.map_or(true, |d| token_map.synthetic_token_id(d.id) != Some(EMPTY_ID))
             }
-        }
-    });
+        })
+        .flat_map(|tt| match tt {
+            tt::TokenTree::Subtree(mut tt) => {
+                reverse_fixups(&mut tt, token_map, undo_info);
+                SmallVec::from_const([tt.into()])
+            }
+            tt::TokenTree::Leaf(leaf) => {
+                if let Some(id) = token_map.synthetic_token_id(leaf.id()) {
+                    let original = undo_info.original[id.0 as usize].clone();
+                    if original.delimiter.is_none() {
+                        original.token_trees.into()
+                    } else {
+                        SmallVec::from_const([original.into()])
+                    }
+                } else {
+                    SmallVec::from_const([leaf.into()])
+                }
+            }
+        })
+        .collect();
 }
 
 #[cfg(test)]
@@ -319,6 +329,31 @@ mod tests {
 
     use super::reverse_fixups;
 
+    // The following three functions are only meant to check partial structural equivalence of
+    // `TokenTree`s, see the last assertion in `check()`.
+    fn check_leaf_eq(a: &tt::Leaf, b: &tt::Leaf) -> bool {
+        match (a, b) {
+            (tt::Leaf::Literal(a), tt::Leaf::Literal(b)) => a.text == b.text,
+            (tt::Leaf::Punct(a), tt::Leaf::Punct(b)) => a.char == b.char,
+            (tt::Leaf::Ident(a), tt::Leaf::Ident(b)) => a.text == b.text,
+            _ => false,
+        }
+    }
+
+    fn check_subtree_eq(a: &tt::Subtree, b: &tt::Subtree) -> bool {
+        a.delimiter.map(|it| it.kind) == b.delimiter.map(|it| it.kind)
+            && a.token_trees.len() == b.token_trees.len()
+            && a.token_trees.iter().zip(&b.token_trees).all(|(a, b)| check_tt_eq(a, b))
+    }
+
+    fn check_tt_eq(a: &tt::TokenTree, b: &tt::TokenTree) -> bool {
+        match (a, b) {
+            (tt::TokenTree::Leaf(a), tt::TokenTree::Leaf(b)) => check_leaf_eq(a, b),
+            (tt::TokenTree::Subtree(a), tt::TokenTree::Subtree(b)) => check_subtree_eq(a, b),
+            _ => false,
+        }
+    }
+
     #[track_caller]
     fn check(ra_fixture: &str, mut expect: Expect) {
         let parsed = syntax::SourceFile::parse(ra_fixture);
@@ -331,17 +366,15 @@ mod tests {
             fixups.append,
         );
 
-        let mut actual = tt.to_string();
-        actual.push('\n');
+        let actual = format!("{}\n", tt);
 
         expect.indent(false);
         expect.assert_eq(&actual);
 
         // the fixed-up tree should be syntactically valid
         let (parse, _) = mbe::token_tree_to_syntax_node(&tt, ::mbe::TopEntryPoint::MacroItems);
-        assert_eq!(
-            parse.errors(),
-            &[],
+        assert!(
+            parse.errors().is_empty(),
             "parse has syntax errors. parse tree:\n{:#?}",
             parse.syntax_node()
         );
@@ -349,9 +382,12 @@ mod tests {
         reverse_fixups(&mut tt, &tmap, &fixups.undo_info);
 
         // the fixed-up + reversed version should be equivalent to the original input
-        // (but token IDs don't matter)
+        // modulo token IDs and `Punct`s' spacing.
         let (original_as_tt, _) = mbe::syntax_node_to_token_tree(&parsed.syntax_node());
-        assert_eq!(tt.to_string(), original_as_tt.to_string());
+        assert!(
+            check_subtree_eq(&tt, &original_as_tt),
+            "different token tree: {tt:?}, {original_as_tt:?}"
+        );
     }
 
     #[test]
@@ -468,7 +504,7 @@ fn foo() {
 }
 "#,
             expect![[r#"
-fn foo () {a .__ra_fixup}
+fn foo () {a . __ra_fixup}
 "#]],
         )
     }
@@ -482,7 +518,7 @@ fn foo() {
 }
 "#,
             expect![[r#"
-fn foo () {a .__ra_fixup ;}
+fn foo () {a . __ra_fixup ;}
 "#]],
         )
     }
@@ -497,7 +533,7 @@ fn foo() {
 }
 "#,
             expect![[r#"
-fn foo () {a .__ra_fixup ; bar () ;}
+fn foo () {a . __ra_fixup ; bar () ;}
 "#]],
         )
     }
@@ -525,7 +561,7 @@ fn foo() {
 }
 "#,
             expect![[r#"
-fn foo () {let x = a .__ra_fixup ;}
+fn foo () {let x = a . __ra_fixup ;}
 "#]],
         )
     }
@@ -541,7 +577,7 @@ fn foo() {
 }
 "#,
             expect![[r#"
-fn foo () {a .b ; bar () ;}
+fn foo () {a . b ; bar () ;}
 "#]],
         )
     }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
index ed13275bab8..a1d6835bfae 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index b68c764bdca..39514fc44e6 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -53,7 +53,7 @@ pub use builder::{ParamKind, TyBuilder};
 pub use chalk_ext::*;
 pub use infer::{
     could_coerce, could_unify, Adjust, Adjustment, AutoBorrow, BindingMode, InferenceDiagnostic,
-    InferenceResult,
+    InferenceResult, OverloadedDeref, PointerCast,
 };
 pub use interner::Interner;
 pub use lower::{
@@ -523,7 +523,7 @@ where
 }
 
 pub fn callable_sig_from_fnonce(
-    self_ty: &Canonical<Ty>,
+    self_ty: &Ty,
     env: Arc<TraitEnvironment>,
     db: &dyn HirDatabase,
 ) -> Option<CallableSig> {
@@ -531,27 +531,28 @@ pub fn callable_sig_from_fnonce(
     let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
     let output_assoc_type = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
 
-    let mut kinds = self_ty.binders.interned().to_vec();
     let b = TyBuilder::trait_ref(db, fn_once_trait);
     if b.remaining() != 2 {
         return None;
     }
-    let fn_once = b
-        .push(self_ty.value.clone())
-        .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
-        .build();
-    kinds.extend(fn_once.substitution.iter(Interner).skip(1).map(|x| {
-        let vk = match x.data(Interner) {
-            chalk_ir::GenericArgData::Ty(_) => {
-                chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
-            }
-            chalk_ir::GenericArgData::Lifetime(_) => chalk_ir::VariableKind::Lifetime,
-            chalk_ir::GenericArgData::Const(c) => {
-                chalk_ir::VariableKind::Const(c.data(Interner).ty.clone())
-            }
-        };
-        chalk_ir::WithKind::new(vk, UniverseIndex::ROOT)
-    }));
+    let fn_once = b.push(self_ty.clone()).fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build();
+    let kinds = fn_once
+        .substitution
+        .iter(Interner)
+        .skip(1)
+        .map(|x| {
+            let vk = match x.data(Interner) {
+                chalk_ir::GenericArgData::Ty(_) => {
+                    chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
+                }
+                chalk_ir::GenericArgData::Lifetime(_) => chalk_ir::VariableKind::Lifetime,
+                chalk_ir::GenericArgData::Const(c) => {
+                    chalk_ir::VariableKind::Const(c.data(Interner).ty.clone())
+                }
+            };
+            chalk_ir::WithKind::new(vk, UniverseIndex::ROOT)
+        })
+        .collect::<Vec<_>>();
 
     // FIXME: chalk refuses to solve `<Self as FnOnce<^0.0>>::Output == ^0.1`, so we first solve
     // `<Self as FnOnce<^0.0>>` and then replace `^0.0` with the concrete argument tuple.
@@ -563,21 +564,16 @@ pub fn callable_sig_from_fnonce(
         Some(Solution::Unique(vars)) => vars.value.subst,
         _ => return None,
     };
-    let args = subst.at(Interner, self_ty.binders.interned().len()).ty(Interner)?;
+    let args = subst.at(Interner, 0).ty(Interner)?;
     let params = match args.kind(Interner) {
         chalk_ir::TyKind::Tuple(_, subst) => {
             subst.iter(Interner).filter_map(|arg| arg.ty(Interner).cloned()).collect::<Vec<_>>()
         }
         _ => return None,
     };
-    if params.iter().any(|ty| ty.is_unknown()) {
-        return None;
-    }
 
-    let fn_once = TyBuilder::trait_ref(db, fn_once_trait)
-        .push(self_ty.value.clone())
-        .push(args.clone())
-        .build();
+    let fn_once =
+        TyBuilder::trait_ref(db, fn_once_trait).push(self_ty.clone()).push(args.clone()).build();
     let projection =
         TyBuilder::assoc_type_projection(db, output_assoc_type, Some(fn_once.substitution.clone()))
             .build();
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
index 50859475e1d..8bcfa2728f0 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
@@ -541,7 +541,7 @@ pub struct ReceiverAdjustments {
 
 impl ReceiverAdjustments {
     pub(crate) fn apply(&self, table: &mut InferenceTable<'_>, ty: Ty) -> (Ty, Vec<Adjustment>) {
-        let mut ty = ty;
+        let mut ty = table.resolve_ty_shallow(&ty);
         let mut adjust = Vec::new();
         for _ in 0..self.autoderefs {
             match autoderef::autoderef_step(table, ty.clone()) {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
index ac8edb841a5..5d76d185ffc 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
@@ -164,16 +164,16 @@ fn infer_associated_method_with_modules() {
     check_infer(
         r#"
         mod a {
-            struct A;
+            pub struct A;
             impl A { pub fn thing() -> A { A {} }}
         }
 
         mod b {
-            struct B;
+            pub struct B;
             impl B { pub fn thing() -> u32 { 99 }}
 
-            mod c {
-                struct C;
+            pub mod c {
+                pub struct C;
                 impl C { pub fn thing() -> C { C {} }}
             }
         }
@@ -186,22 +186,22 @@ fn infer_associated_method_with_modules() {
         }
         "#,
         expect![[r#"
-            55..63 '{ A {} }': A
-            57..61 'A {}': A
-            125..131 '{ 99 }': u32
-            127..129 '99': u32
-            201..209 '{ C {} }': C
-            203..207 'C {}': C
-            240..324 '{     ...g(); }': ()
-            250..251 'x': A
-            254..265 'a::A::thing': fn thing() -> A
-            254..267 'a::A::thing()': A
-            277..278 'y': u32
-            281..292 'b::B::thing': fn thing() -> u32
-            281..294 'b::B::thing()': u32
-            304..305 'z': C
-            308..319 'c::C::thing': fn thing() -> C
-            308..321 'c::C::thing()': C
+            59..67 '{ A {} }': A
+            61..65 'A {}': A
+            133..139 '{ 99 }': u32
+            135..137 '99': u32
+            217..225 '{ C {} }': C
+            219..223 'C {}': C
+            256..340 '{     ...g(); }': ()
+            266..267 'x': A
+            270..281 'a::A::thing': fn thing() -> A
+            270..283 'a::A::thing()': A
+            293..294 'y': u32
+            297..308 'b::B::thing': fn thing() -> u32
+            297..310 'b::B::thing()': u32
+            320..321 'z': C
+            324..335 'c::C::thing': fn thing() -> C
+            324..337 'c::C::thing()': C
         "#]],
     );
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
index a155adcec6c..4e46397459d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
@@ -1707,3 +1707,19 @@ impl<T, const N: usize> Trait for [T; N] {
         "#,
     );
 }
+
+#[test]
+fn unsize_array_with_inference_variable() {
+    check_types(
+        r#"
+//- minicore: try, slice
+use core::ops::ControlFlow;
+fn foo() -> ControlFlow<(), [usize; 1]> { loop {} }
+fn bar() -> ControlFlow<(), ()> {
+    let a = foo()?.len();
+      //^ usize
+    ControlFlow::Continue(())
+}
+"#,
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
index 080e2ac1b8e..d7431443b83 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
@@ -214,7 +214,7 @@ fn infer_paths() {
 fn a() -> u32 { 1 }
 
 mod b {
-    fn c() -> u32 { 1 }
+    pub fn c() -> u32 { 1 }
 }
 
 fn test() {
@@ -225,13 +225,13 @@ fn test() {
         expect![[r#"
             14..19 '{ 1 }': u32
             16..17 '1': u32
-            47..52 '{ 1 }': u32
-            49..50 '1': u32
-            66..90 '{     ...c(); }': ()
-            72..73 'a': fn a() -> u32
-            72..75 'a()': u32
-            81..85 'b::c': fn c() -> u32
-            81..87 'b::c()': u32
+            51..56 '{ 1 }': u32
+            53..54 '1': u32
+            70..94 '{     ...c(); }': ()
+            76..77 'a': fn a() -> u32
+            76..79 'a()': u32
+            85..89 'b::c': fn c() -> u32
+            85..91 'b::c()': u32
         "#]],
     );
 }
@@ -1856,7 +1856,7 @@ fn not_shadowing_module_by_primitive() {
     check_types(
         r#"
 //- /str.rs
-fn foo() -> u32 {0}
+pub fn foo() -> u32 {0}
 
 //- /main.rs
 mod str;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
index 7d42b8b9bc8..3d7194b6f44 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
@@ -1706,7 +1706,7 @@ fn where_clause_trait_in_scope_for_method_resolution() {
     check_types(
         r#"
 mod foo {
-    trait Trait {
+    pub trait Trait {
         fn foo(&self) -> u32 { 0 }
     }
 }
@@ -1723,7 +1723,7 @@ fn super_trait_method_resolution() {
     check_infer(
         r#"
 mod foo {
-    trait SuperTrait {
+    pub trait SuperTrait {
         fn foo(&self) -> u32 {}
     }
 }
@@ -1735,15 +1735,15 @@ fn test<T: Trait1, U: Trait2>(x: T, y: U) {
     y.foo();
 }"#,
         expect![[r#"
-            49..53 'self': &Self
-            62..64 '{}': u32
-            181..182 'x': T
-            187..188 'y': U
-            193..222 '{     ...o(); }': ()
-            199..200 'x': T
-            199..206 'x.foo()': u32
-            212..213 'y': U
-            212..219 'y.foo()': u32
+            53..57 'self': &Self
+            66..68 '{}': u32
+            185..186 'x': T
+            191..192 'y': U
+            197..226 '{     ...o(); }': ()
+            203..204 'x': T
+            203..210 'x.foo()': u32
+            216..217 'y': U
+            216..223 'y.foo()': u32
         "#]],
     );
 }
@@ -1754,7 +1754,7 @@ fn super_trait_impl_trait_method_resolution() {
         r#"
 //- minicore: sized
 mod foo {
-    trait SuperTrait {
+    pub trait SuperTrait {
         fn foo(&self) -> u32 {}
     }
 }
@@ -1764,12 +1764,12 @@ fn test(x: &impl Trait1) {
     x.foo();
 }"#,
         expect![[r#"
-            49..53 'self': &Self
-            62..64 '{}': u32
-            115..116 'x': &impl Trait1
-            132..148 '{     ...o(); }': ()
-            138..139 'x': &impl Trait1
-            138..145 'x.foo()': u32
+            53..57 'self': &Self
+            66..68 '{}': u32
+            119..120 'x': &impl Trait1
+            136..152 '{     ...o(); }': ()
+            142..143 'x': &impl Trait1
+            142..149 'x.foo()': u32
         "#]],
     );
 }
diff --git a/src/tools/rust-analyzer/crates/hir/Cargo.toml b/src/tools/rust-analyzer/crates/hir/Cargo.toml
index e1418de3cdc..f780e3f53c8 100644
--- a/src/tools/rust-analyzer/crates/hir/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index cbd9bf32a54..cbbcaebb428 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -117,7 +117,7 @@ pub use {
         name::{known, Name},
         ExpandResult, HirFileId, InFile, MacroFile, Origin,
     },
-    hir_ty::display::HirDisplay,
+    hir_ty::{display::HirDisplay, PointerCast, Safety},
 };
 
 // These are negative re-exports: pub using these names is forbidden, they
@@ -2997,8 +2997,7 @@ impl Type {
             TyKind::Function(_) => Callee::FnPtr,
             TyKind::FnDef(..) => Callee::Def(self.ty.callable_def(db)?),
             _ => {
-                let ty = hir_ty::replace_errors_with_variables(&self.ty);
-                let sig = hir_ty::callable_sig_from_fnonce(&ty, self.env.clone(), db)?;
+                let sig = hir_ty::callable_sig_from_fnonce(&self.ty, self.env.clone(), db)?;
                 return Some(Callable {
                     ty: self.clone(),
                     sig,
@@ -3651,6 +3650,28 @@ impl From<ItemInNs> for ScopeDef {
     }
 }
 
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub enum Adjust {
+    /// Go from ! to any type.
+    NeverToAny,
+    /// Dereference once, producing a place.
+    Deref(Option<OverloadedDeref>),
+    /// Take the address and produce either a `&` or `*` pointer.
+    Borrow(AutoBorrow),
+    Pointer(PointerCast),
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub enum AutoBorrow {
+    /// Converts from T to &T.
+    Ref(Mutability),
+    /// Converts from T to *T.
+    RawPtr(Mutability),
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub struct OverloadedDeref(pub Mutability);
+
 pub trait HasVisibility {
     fn visibility(&self, db: &dyn HirDatabase) -> Visibility;
     fn is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool {
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index 119ec3210e1..2e1f88ba090 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -29,9 +29,10 @@ use crate::{
     db::HirDatabase,
     semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
     source_analyzer::{resolve_hir_path, SourceAnalyzer},
-    Access, BindingMode, BuiltinAttr, Callable, ConstParam, Crate, DeriveHelper, Field, Function,
-    HasSource, HirFileId, Impl, InFile, Label, LifetimeParam, Local, Macro, Module, ModuleDef,
-    Name, Path, ScopeDef, ToolModule, Trait, Type, TypeAlias, TypeParam, VariantDef,
+    Access, Adjust, AutoBorrow, BindingMode, BuiltinAttr, Callable, ConstParam, Crate,
+    DeriveHelper, Field, Function, HasSource, HirFileId, Impl, InFile, Label, LifetimeParam, Local,
+    Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, ToolModule, Trait, Type,
+    TypeAlias, TypeParam, VariantDef,
 };
 
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -333,9 +334,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
         self.imp.resolve_trait(trait_)
     }
 
-    // FIXME: Figure out a nice interface to inspect adjustments
-    pub fn is_implicit_reborrow(&self, expr: &ast::Expr) -> Option<Mutability> {
-        self.imp.is_implicit_reborrow(expr)
+    pub fn expr_adjustments(&self, expr: &ast::Expr) -> Option<Vec<Adjust>> {
+        self.imp.expr_adjustments(expr)
     }
 
     pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<TypeInfo> {
@@ -1067,8 +1067,29 @@ impl<'db> SemanticsImpl<'db> {
         }
     }
 
-    fn is_implicit_reborrow(&self, expr: &ast::Expr) -> Option<Mutability> {
-        self.analyze(expr.syntax())?.is_implicit_reborrow(self.db, expr)
+    fn expr_adjustments(&self, expr: &ast::Expr) -> Option<Vec<Adjust>> {
+        let mutability = |m| match m {
+            hir_ty::Mutability::Not => Mutability::Shared,
+            hir_ty::Mutability::Mut => Mutability::Mut,
+        };
+        self.analyze(expr.syntax())?.expr_adjustments(self.db, expr).map(|it| {
+            it.iter()
+                .map(|adjust| match adjust.kind {
+                    hir_ty::Adjust::NeverToAny => Adjust::NeverToAny,
+                    hir_ty::Adjust::Deref(Some(hir_ty::OverloadedDeref(m))) => {
+                        Adjust::Deref(Some(OverloadedDeref(mutability(m))))
+                    }
+                    hir_ty::Adjust::Deref(None) => Adjust::Deref(None),
+                    hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::RawPtr(m)) => {
+                        Adjust::Borrow(AutoBorrow::RawPtr(mutability(m)))
+                    }
+                    hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::Ref(m)) => {
+                        Adjust::Borrow(AutoBorrow::Ref(mutability(m)))
+                    }
+                    hir_ty::Adjust::Pointer(pc) => Adjust::Pointer(pc),
+                })
+                .collect()
+        })
     }
 
     fn type_of_expr(&self, expr: &ast::Expr) -> Option<TypeInfo> {
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
index f86c5710053..91ea1c24d14 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -38,8 +38,7 @@ use hir_ty::{
         UnsafeExpr,
     },
     method_resolution::{self, lang_names_for_bin_op},
-    Adjust, Adjustment, AutoBorrow, InferenceResult, Interner, Substitution, Ty, TyExt, TyKind,
-    TyLoweringContext,
+    Adjustment, InferenceResult, Interner, Substitution, Ty, TyExt, TyKind, TyLoweringContext,
 };
 use itertools::Itertools;
 use smallvec::SmallVec;
@@ -156,21 +155,14 @@ impl SourceAnalyzer {
         Some(res)
     }
 
-    pub(crate) fn is_implicit_reborrow(
+    pub(crate) fn expr_adjustments(
         &self,
         db: &dyn HirDatabase,
         expr: &ast::Expr,
-    ) -> Option<Mutability> {
+    ) -> Option<&[Adjustment]> {
         let expr_id = self.expr_id(db, expr)?;
         let infer = self.infer.as_ref()?;
-        let adjustments = infer.expr_adjustments.get(&expr_id)?;
-        adjustments.windows(2).find_map(|slice| match slice {
-            &[Adjustment {kind: Adjust::Deref(None), ..}, Adjustment {kind: Adjust::Borrow(AutoBorrow::Ref(m)), ..}] => Some(match m {
-                hir_ty::Mutability::Mut => Mutability::Mut,
-                hir_ty::Mutability::Not => Mutability::Shared,
-            }),
-            _ => None,
-        })
+        infer.expr_adjustments.get(&expr_id).map(|v| &**v)
     }
 
     pub(crate) fn type_of_expr(
diff --git a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
index 57a41f3d9a9..e781c0a016d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
index 62cf5ab4f37..2b3793659cf 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
@@ -196,6 +196,7 @@ trait Foo {
     type Output;
 
     const CONST: usize = 42;
+    const CONST_2: i32;
 
     fn foo(&self);
     fn bar(&self);
@@ -213,6 +214,7 @@ trait Foo {
     type Output;
 
     const CONST: usize = 42;
+    const CONST_2: i32;
 
     fn foo(&self);
     fn bar(&self);
@@ -226,7 +228,7 @@ impl Foo for S {
 
     $0type Output;
 
-    const CONST: usize = 42;
+    const CONST_2: i32;
 
     fn foo(&self) {
         todo!()
@@ -379,14 +381,14 @@ impl Foo for S {
             r#"
 mod foo {
     pub struct Bar;
-    trait Foo { fn foo(&self, bar: Bar); }
+    pub trait Foo { fn foo(&self, bar: Bar); }
 }
 struct S;
 impl foo::Foo for S { $0 }"#,
             r#"
 mod foo {
     pub struct Bar;
-    trait Foo { fn foo(&self, bar: Bar); }
+    pub trait Foo { fn foo(&self, bar: Bar); }
 }
 struct S;
 impl foo::Foo for S {
@@ -439,14 +441,14 @@ impl bar::Foo for S {
             r#"
 mod foo {
     pub struct Bar<T>;
-    trait Foo { fn foo(&self, bar: Bar<u32>); }
+    pub trait Foo { fn foo(&self, bar: Bar<u32>); }
 }
 struct S;
 impl foo::Foo for S { $0 }"#,
             r#"
 mod foo {
     pub struct Bar<T>;
-    trait Foo { fn foo(&self, bar: Bar<u32>); }
+    pub trait Foo { fn foo(&self, bar: Bar<u32>); }
 }
 struct S;
 impl foo::Foo for S {
@@ -464,14 +466,14 @@ impl foo::Foo for S {
             r#"
 mod foo {
     pub struct Bar<T>;
-    trait Foo<T> { fn foo(&self, bar: Bar<T>); }
+    pub trait Foo<T> { fn foo(&self, bar: Bar<T>); }
 }
 struct S;
 impl foo::Foo<u32> for S { $0 }"#,
             r#"
 mod foo {
     pub struct Bar<T>;
-    trait Foo<T> { fn foo(&self, bar: Bar<T>); }
+    pub trait Foo<T> { fn foo(&self, bar: Bar<T>); }
 }
 struct S;
 impl foo::Foo<u32> for S {
@@ -489,7 +491,7 @@ impl foo::Foo<u32> for S {
             add_missing_impl_members,
             r#"
 mod foo {
-    trait Foo<T> { fn foo(&self, bar: T); }
+    pub trait Foo<T> { fn foo(&self, bar: T); }
     pub struct Param;
 }
 struct Param;
@@ -497,7 +499,7 @@ struct S;
 impl foo::Foo<Param> for S { $0 }"#,
             r#"
 mod foo {
-    trait Foo<T> { fn foo(&self, bar: T); }
+    pub trait Foo<T> { fn foo(&self, bar: T); }
     pub struct Param;
 }
 struct Param;
@@ -518,7 +520,7 @@ impl foo::Foo<Param> for S {
 mod foo {
     pub struct Bar<T>;
     impl Bar<T> { type Assoc = u32; }
-    trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
+    pub trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
 }
 struct S;
 impl foo::Foo for S { $0 }"#,
@@ -526,7 +528,7 @@ impl foo::Foo for S { $0 }"#,
 mod foo {
     pub struct Bar<T>;
     impl Bar<T> { type Assoc = u32; }
-    trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
+    pub trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
 }
 struct S;
 impl foo::Foo for S {
@@ -545,7 +547,7 @@ impl foo::Foo for S {
 mod foo {
     pub struct Bar<T>;
     pub struct Baz;
-    trait Foo { fn foo(&self, bar: Bar<Baz>); }
+    pub trait Foo { fn foo(&self, bar: Bar<Baz>); }
 }
 struct S;
 impl foo::Foo for S { $0 }"#,
@@ -553,7 +555,7 @@ impl foo::Foo for S { $0 }"#,
 mod foo {
     pub struct Bar<T>;
     pub struct Baz;
-    trait Foo { fn foo(&self, bar: Bar<Baz>); }
+    pub trait Foo { fn foo(&self, bar: Bar<Baz>); }
 }
 struct S;
 impl foo::Foo for S {
@@ -571,14 +573,14 @@ impl foo::Foo for S {
             r#"
 mod foo {
     pub trait Fn<Args> { type Output; }
-    trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
+    pub trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
 }
 struct S;
 impl foo::Foo for S { $0 }"#,
             r#"
 mod foo {
     pub trait Fn<Args> { type Output; }
-    trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
+    pub trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
 }
 struct S;
 impl foo::Foo for S {
@@ -658,6 +660,7 @@ trait Foo {
     type Output;
 
     const CONST: usize = 42;
+    const CONST_2: i32;
 
     fn valid(some: u32) -> bool { false }
     fn foo(some: u32) -> bool;
@@ -669,13 +672,16 @@ trait Foo {
     type Output;
 
     const CONST: usize = 42;
+    const CONST_2: i32;
 
     fn valid(some: u32) -> bool { false }
     fn foo(some: u32) -> bool;
 }
 struct S;
 impl Foo for S {
-    $0fn valid(some: u32) -> bool { false }
+    $0const CONST: usize = 42;
+
+    fn valid(some: u32) -> bool { false }
 }"#,
         )
     }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
index 06058835849..c1e2f19ab18 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
@@ -109,8 +109,6 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
             let params =
                 body.extracted_function_params(ctx, &container_info, locals_used.iter().copied());
 
-            let extracted_from_trait_impl = body.extracted_from_trait_impl();
-
             let name = make_function_name(&semantics_scope);
 
             let fun = Function {
@@ -129,8 +127,11 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
 
             builder.replace(target_range, make_call(ctx, &fun, old_indent));
 
+            let has_impl_wrapper =
+                insert_after.ancestors().any(|a| a.kind() == SyntaxKind::IMPL && a != insert_after);
+
             let fn_def = match fun.self_param_adt(ctx) {
-                Some(adt) if extracted_from_trait_impl => {
+                Some(adt) if anchor == Anchor::Method && !has_impl_wrapper => {
                     let fn_def = format_function(ctx, module, &fun, old_indent, new_indent + 1);
                     generate_impl_text(&adt, &fn_def).replace("{\n\n", "{")
                 }
@@ -272,7 +273,7 @@ enum FunType {
 }
 
 /// Where to put extracted function definition
-#[derive(Debug)]
+#[derive(Debug, Eq, PartialEq, Clone, Copy)]
 enum Anchor {
     /// Extract free function and put right after current top-level function
     Freestanding,
@@ -1245,6 +1246,14 @@ fn node_to_insert_after(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNod
     while let Some(next_ancestor) = ancestors.next() {
         match next_ancestor.kind() {
             SyntaxKind::SOURCE_FILE => break,
+            SyntaxKind::IMPL => {
+                if body.extracted_from_trait_impl() && matches!(anchor, Anchor::Method) {
+                    let impl_node = find_non_trait_impl(&next_ancestor);
+                    if let target_node @ Some(_) = impl_node.as_ref().and_then(last_impl_member) {
+                        return target_node;
+                    }
+                }
+            }
             SyntaxKind::ITEM_LIST if !matches!(anchor, Anchor::Freestanding) => continue,
             SyntaxKind::ITEM_LIST => {
                 if ancestors.peek().map(SyntaxNode::kind) == Some(SyntaxKind::MODULE) {
@@ -1265,6 +1274,29 @@ fn node_to_insert_after(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNod
     last_ancestor
 }
 
+fn find_non_trait_impl(trait_impl: &SyntaxNode) -> Option<ast::Impl> {
+    let as_impl = ast::Impl::cast(trait_impl.clone())?;
+    let impl_type = Some(impl_type_name(&as_impl)?);
+
+    let sibblings = trait_impl.parent()?.children();
+    sibblings
+        .filter_map(ast::Impl::cast)
+        .find(|s| impl_type_name(s) == impl_type && !is_trait_impl(s))
+}
+
+fn last_impl_member(impl_node: &ast::Impl) -> Option<SyntaxNode> {
+    let last_child = impl_node.assoc_item_list()?.assoc_items().last()?;
+    Some(last_child.syntax().clone())
+}
+
+fn is_trait_impl(node: &ast::Impl) -> bool {
+    node.trait_().is_some()
+}
+
+fn impl_type_name(impl_node: &ast::Impl) -> Option<String> {
+    Some(impl_node.self_ty()?.to_string())
+}
+
 fn make_call(ctx: &AssistContext<'_>, fun: &Function, indent: IndentLevel) -> String {
     let ret_ty = fun.return_type(ctx);
 
@@ -5052,6 +5084,236 @@ impl Struct {
     }
 
     #[test]
+    fn extract_method_from_trait_with_existing_non_empty_impl_block() {
+        check_assist(
+            extract_function,
+            r#"
+struct Struct(i32);
+trait Trait {
+    fn bar(&self) -> i32;
+}
+
+impl Struct {
+    fn foo() {}
+}
+
+impl Trait for Struct {
+    fn bar(&self) -> i32 {
+        $0self.0 + 2$0
+    }
+}
+"#,
+            r#"
+struct Struct(i32);
+trait Trait {
+    fn bar(&self) -> i32;
+}
+
+impl Struct {
+    fn foo() {}
+
+    fn $0fun_name(&self) -> i32 {
+        self.0 + 2
+    }
+}
+
+impl Trait for Struct {
+    fn bar(&self) -> i32 {
+        self.fun_name()
+    }
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn extract_function_from_trait_with_existing_non_empty_impl_block() {
+        check_assist(
+            extract_function,
+            r#"
+struct Struct(i32);
+trait Trait {
+    fn bar(&self) -> i32;
+}
+
+impl Struct {
+    fn foo() {}
+}
+
+impl Trait for Struct {
+    fn bar(&self) -> i32 {
+        let three_squared = $03 * 3$0;
+        self.0 + three_squared
+    }
+}
+"#,
+            r#"
+struct Struct(i32);
+trait Trait {
+    fn bar(&self) -> i32;
+}
+
+impl Struct {
+    fn foo() {}
+}
+
+impl Trait for Struct {
+    fn bar(&self) -> i32 {
+        let three_squared = fun_name();
+        self.0 + three_squared
+    }
+}
+
+fn $0fun_name() -> i32 {
+    3 * 3
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn extract_method_from_trait_with_multiple_existing_impl_blocks() {
+        check_assist(
+            extract_function,
+            r#"
+struct Struct(i32);
+struct StructBefore(i32);
+struct StructAfter(i32);
+trait Trait {
+    fn bar(&self) -> i32;
+}
+
+impl StructBefore {
+    fn foo(){}
+}
+
+impl Struct {
+    fn foo(){}
+}
+
+impl StructAfter {
+    fn foo(){}
+}
+
+impl Trait for Struct {
+    fn bar(&self) -> i32 {
+        $0self.0 + 2$0
+    }
+}
+"#,
+            r#"
+struct Struct(i32);
+struct StructBefore(i32);
+struct StructAfter(i32);
+trait Trait {
+    fn bar(&self) -> i32;
+}
+
+impl StructBefore {
+    fn foo(){}
+}
+
+impl Struct {
+    fn foo(){}
+
+    fn $0fun_name(&self) -> i32 {
+        self.0 + 2
+    }
+}
+
+impl StructAfter {
+    fn foo(){}
+}
+
+impl Trait for Struct {
+    fn bar(&self) -> i32 {
+        self.fun_name()
+    }
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn extract_method_from_trait_with_multiple_existing_trait_impl_blocks() {
+        check_assist(
+            extract_function,
+            r#"
+struct Struct(i32);
+trait Trait {
+    fn bar(&self) -> i32;
+}
+trait TraitBefore {
+    fn before(&self) -> i32;
+}
+trait TraitAfter {
+    fn after(&self) -> i32;
+}
+
+impl TraitBefore for Struct {
+    fn before(&self) -> i32 {
+        42
+    }
+}
+
+impl Struct {
+    fn foo(){}
+}
+
+impl TraitAfter for Struct {
+    fn after(&self) -> i32 {
+        42
+    }
+}
+
+impl Trait for Struct {
+    fn bar(&self) -> i32 {
+        $0self.0 + 2$0
+    }
+}
+"#,
+            r#"
+struct Struct(i32);
+trait Trait {
+    fn bar(&self) -> i32;
+}
+trait TraitBefore {
+    fn before(&self) -> i32;
+}
+trait TraitAfter {
+    fn after(&self) -> i32;
+}
+
+impl TraitBefore for Struct {
+    fn before(&self) -> i32 {
+        42
+    }
+}
+
+impl Struct {
+    fn foo(){}
+
+    fn $0fun_name(&self) -> i32 {
+        self.0 + 2
+    }
+}
+
+impl TraitAfter for Struct {
+    fn after(&self) -> i32 {
+        42
+    }
+}
+
+impl Trait for Struct {
+    fn bar(&self) -> i32 {
+        self.fun_name()
+    }
+}
+"#,
+        )
+    }
+
+    #[test]
     fn closure_arguments() {
         check_assist(
             extract_function,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs
index 87645430287..d9e00435ecf 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs
@@ -1,4 +1,4 @@
-use hir::{db::HirDatabase, HasSource, HasVisibility, PathResolution};
+use hir::{db::HirDatabase, HasSource, HasVisibility, ModuleDef, PathResolution, ScopeDef};
 use ide_db::base_db::FileId;
 use syntax::{
     ast::{self, HasVisibility as _},
@@ -18,7 +18,7 @@ use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists};
 //     fn frobnicate() {}
 // }
 // fn main() {
-//     m::frobnicate$0() {}
+//     m::frobnicate$0();
 // }
 // ```
 // ->
@@ -27,7 +27,7 @@ use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists};
 //     $0pub(crate) fn frobnicate() {}
 // }
 // fn main() {
-//     m::frobnicate() {}
+//     m::frobnicate();
 // }
 // ```
 pub(crate) fn fix_visibility(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
@@ -37,11 +37,15 @@ pub(crate) fn fix_visibility(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
 
 fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     let path: ast::Path = ctx.find_node_at_offset()?;
-    let path_res = ctx.sema.resolve_path(&path)?;
-    let def = match path_res {
-        PathResolution::Def(def) => def,
-        _ => return None,
-    };
+    let qualifier = path.qualifier()?;
+    let name_ref = path.segment()?.name_ref()?;
+    let qualifier_res = ctx.sema.resolve_path(&qualifier)?;
+    let PathResolution::Def(ModuleDef::Module(module)) = qualifier_res else { return None; };
+    let (_, def) = module
+        .scope(ctx.db(), None)
+        .into_iter()
+        .find(|(name, _)| name.to_smol_str() == name_ref.text().as_str())?;
+    let ScopeDef::ModuleDef(def) = def else { return None; };
 
     let current_module = ctx.sema.scope(path.syntax())?.module();
     let target_module = def.module(ctx.db())?;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs
index 35cd42908af..0bcb5728311 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs
@@ -261,12 +261,12 @@ fn main() {
 }
 
 //- /foo.rs
-enum Foo {
+pub enum Foo {
     Bar,
 }
 ",
             r"
-enum Foo {
+pub enum Foo {
     Bar,
     Baz,
 }
@@ -310,7 +310,7 @@ fn main() {
             generate_enum_variant,
             r"
 mod m {
-    enum Foo {
+    pub enum Foo {
         Bar,
     }
 }
@@ -320,7 +320,7 @@ fn main() {
 ",
             r"
 mod m {
-    enum Foo {
+    pub enum Foo {
         Bar,
         Baz,
     }
@@ -516,10 +516,10 @@ mod foo;
 use foo::Foo::Bar$0;
 
 //- /foo.rs
-enum Foo {}
+pub enum Foo {}
 ",
             r"
-enum Foo {
+pub enum Foo {
     Bar,
 }
 ",
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
index c229127e48f..57f198748cb 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
@@ -1324,7 +1324,7 @@ fn foo() {
             generate_function,
             r"
 mod bar {
-    mod baz {}
+    pub mod baz {}
 }
 
 fn foo() {
@@ -1333,7 +1333,7 @@ fn foo() {
 ",
             r"
 mod bar {
-    mod baz {
+    pub mod baz {
         pub(crate) fn my_fn() {
             ${0:todo!()}
         }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_format_string_arg.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_format_string_arg.rs
index aa710d2ce65..11db6ae7f7b 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_format_string_arg.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_format_string_arg.rs
@@ -92,7 +92,7 @@ pub(crate) fn move_format_string_arg(acc: &mut Assists, ctx: &AssistContext<'_>)
                         NodeOrToken::Node(n) => {
                             format_to!(current_arg, "{n}");
                         },
-                        NodeOrToken::Token(t) if t.kind() == COMMA=> {
+                        NodeOrToken::Token(t) if t.kind() == COMMA => {
                             existing_args.push(current_arg.trim().into());
                             current_arg.clear();
                         },
@@ -238,14 +238,14 @@ fn main() {
             &add_macro_decl(
                 r#"
 fn main() {
-    print!("{} {x + 1:b} {Struct(1, 2)}$0", 1);
+    print!("{:b} {x + 1:b} {Struct(1, 2)}$0", 1);
 }
 "#,
             ),
             &add_macro_decl(
                 r#"
 fn main() {
-    print!("{} {:b} {}"$0, 1, x + 1, Struct(1, 2));
+    print!("{:b} {:b} {}"$0, 1, x + 1, Struct(1, 2));
 }
 "#,
             ),
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs
index 3d9cbff177b..99ae60e07bc 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs
@@ -1,7 +1,7 @@
 use itertools::Itertools;
 use syntax::{
     ast::{self, AstNode, AstToken},
-    match_ast, NodeOrToken, SyntaxElement, TextSize, T,
+    match_ast, NodeOrToken, SyntaxElement, TextRange, TextSize, T,
 };
 
 use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -22,7 +22,36 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
 // }
 // ```
 pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
-    let macro_call = ctx.find_node_at_offset::<ast::MacroCall>()?;
+    let macro_calls = if ctx.has_empty_selection() {
+        vec![ctx.find_node_at_offset::<ast::MacroCall>()?]
+    } else {
+        ctx.covering_element()
+            .as_node()?
+            .descendants()
+            .filter(|node| ctx.selection_trimmed().contains_range(node.text_range()))
+            .filter_map(ast::MacroCall::cast)
+            .collect()
+    };
+
+    let replacements =
+        macro_calls.into_iter().filter_map(compute_dbg_replacement).collect::<Vec<_>>();
+    if replacements.is_empty() {
+        return None;
+    }
+
+    acc.add(
+        AssistId("remove_dbg", AssistKind::Refactor),
+        "Remove dbg!()",
+        ctx.selection_trimmed(),
+        |builder| {
+            for (range, text) in replacements {
+                builder.replace(range, text);
+            }
+        },
+    )
+}
+
+fn compute_dbg_replacement(macro_call: ast::MacroCall) -> Option<(TextRange, String)> {
     let tt = macro_call.token_tree()?;
     let r_delim = NodeOrToken::Token(tt.right_delimiter_token()?);
     if macro_call.path()?.segment()?.name_ref()?.text() != "dbg"
@@ -41,7 +70,7 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
 
     let macro_expr = ast::MacroExpr::cast(macro_call.syntax().parent()?)?;
     let parent = macro_expr.syntax().parent()?;
-    let (range, text) = match &*input_expressions {
+    Some(match &*input_expressions {
         // dbg!()
         [] => {
             match_ast! {
@@ -107,10 +136,6 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
         }
         // dbg!(expr0, expr1, ...)
         exprs => (macro_call.syntax().text_range(), format!("({})", exprs.iter().format(", "))),
-    };
-
-    acc.add(AssistId("remove_dbg", AssistKind::Refactor), "Remove dbg!()", range, |builder| {
-        builder.replace(range, text);
     })
 }
 
@@ -238,4 +263,28 @@ fn foo() {
         check(r#"$0dbg!(0, 1)"#, r#"(0, 1)"#);
         check(r#"$0dbg!(0, (1, 2))"#, r#"(0, (1, 2))"#);
     }
+
+    #[test]
+    fn test_range() {
+        check(
+            r#"
+fn f() {
+    dbg!(0) + $0dbg!(1);
+    dbg!(())$0
+}
+"#,
+            r#"
+fn f() {
+    dbg!(0) + 1;
+    ()
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_range_partial() {
+        check_assist_not_applicable(remove_dbg, r#"$0dbg$0!(0)"#);
+        check_assist_not_applicable(remove_dbg, r#"$0dbg!(0$0)"#);
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
index f9ba289ee17..6fa15b28e4e 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -1019,8 +1019,6 @@ struct Foo {
 impl foo::Bar for Foo {
     $0type Qux;
 
-    const Baz: usize = 42;
-
     const Fez: usize;
 
     fn foo() {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
index 029d169899b..c09317572ac 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
@@ -741,7 +741,7 @@ mod m {
     fn frobnicate() {}
 }
 fn main() {
-    m::frobnicate$0() {}
+    m::frobnicate$0();
 }
 "#####,
         r#####"
@@ -749,7 +749,7 @@ mod m {
     $0pub(crate) fn frobnicate() {}
 }
 fn main() {
-    m::frobnicate() {}
+    m::frobnicate();
 }
 "#####,
     )
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
index 307e6792705..68c31b4f8e9 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
@@ -119,6 +119,10 @@ pub fn filter_assoc_items(
                 (default_methods, def.body()),
                 (DefaultMethods::Only, Some(_)) | (DefaultMethods::No, None)
             ),
+            ast::AssocItem::Const(def) => matches!(
+                (default_methods, def.body()),
+                (DefaultMethods::Only, Some(_)) | (DefaultMethods::No, None)
+            ),
             _ => default_methods == DefaultMethods::No,
         })
         .collect::<Vec<_>>()
diff --git a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
index 75835bce95d..11310e2f129 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
index e82cbfdcb84..7384a3f2d80 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
@@ -157,7 +157,7 @@ fn complete_trait_impl(
                     add_function_impl(acc, ctx, replacement_range, func, hir_impl)
                 }
                 (hir::AssocItem::TypeAlias(type_alias), All | TypeAlias) => {
-                    add_type_alias_impl(acc, ctx, replacement_range, type_alias)
+                    add_type_alias_impl(acc, ctx, replacement_range, type_alias, hir_impl)
                 }
                 (hir::AssocItem::Const(const_), All | Const) => {
                     add_const_impl(acc, ctx, replacement_range, const_, hir_impl)
@@ -236,9 +236,7 @@ fn get_transformed_assoc_item(
     );
 
     transform.apply(assoc_item.syntax());
-    if let ast::AssocItem::Fn(func) = &assoc_item {
-        func.remove_attrs_and_docs();
-    }
+    assoc_item.remove_attrs_and_docs();
     Some(assoc_item)
 }
 
@@ -247,24 +245,50 @@ fn add_type_alias_impl(
     ctx: &CompletionContext<'_>,
     replacement_range: TextRange,
     type_alias: hir::TypeAlias,
+    impl_def: hir::Impl,
 ) {
-    let alias_name = type_alias.name(ctx.db);
-    let (alias_name, escaped_name) =
-        (alias_name.unescaped().to_smol_str(), alias_name.to_smol_str());
+    let alias_name = type_alias.name(ctx.db).unescaped().to_smol_str();
 
     let label = format!("type {} =", alias_name);
-    let replacement = format!("type {} = ", escaped_name);
 
     let mut item = CompletionItem::new(SymbolKind::TypeAlias, replacement_range, label);
     item.lookup_by(format!("type {}", alias_name))
         .set_documentation(type_alias.docs(ctx.db))
         .set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() });
-    match ctx.config.snippet_cap {
-        Some(cap) => item
-            .snippet_edit(cap, TextEdit::replace(replacement_range, format!("{}$0;", replacement))),
-        None => item.text_edit(TextEdit::replace(replacement_range, replacement)),
-    };
-    item.add_to(acc);
+
+    if let Some(source) = ctx.sema.source(type_alias) {
+        let assoc_item = ast::AssocItem::TypeAlias(source.value);
+        if let Some(transformed_item) = get_transformed_assoc_item(ctx, assoc_item, impl_def) {
+            let transformed_ty = match transformed_item {
+                ast::AssocItem::TypeAlias(ty) => ty,
+                _ => unreachable!(),
+            };
+
+            let start = transformed_ty.syntax().text_range().start();
+            let Some(end) = transformed_ty
+                .eq_token()
+                .map(|tok| tok.text_range().start())
+                .or(transformed_ty.semicolon_token().map(|tok| tok.text_range().start())) else { return };
+
+            let len = end - start;
+            let mut decl = transformed_ty.syntax().text().slice(..len).to_string();
+            if !decl.ends_with(' ') {
+                decl.push(' ');
+            }
+            decl.push_str("= ");
+
+            match ctx.config.snippet_cap {
+                Some(cap) => {
+                    let snippet = format!("{}$0;", decl);
+                    item.snippet_edit(cap, TextEdit::replace(replacement_range, snippet));
+                }
+                None => {
+                    item.text_edit(TextEdit::replace(replacement_range, decl));
+                }
+            };
+            item.add_to(acc);
+        }
+    }
 }
 
 fn add_const_impl(
@@ -309,7 +333,6 @@ fn add_const_impl(
 }
 
 fn make_const_compl_syntax(const_: &ast::Const, needs_whitespace: bool) -> String {
-    const_.remove_attrs_and_docs();
     let const_ = if needs_whitespace {
         insert_whitespace_into_node::insert_ws_into(const_.syntax().clone())
     } else {
@@ -333,8 +356,6 @@ fn make_const_compl_syntax(const_: &ast::Const, needs_whitespace: bool) -> Strin
 }
 
 fn function_declaration(node: &ast::Fn, needs_whitespace: bool) -> String {
-    node.remove_attrs_and_docs();
-
     let node = if needs_whitespace {
         insert_whitespace_into_node::insert_ws_into(node.syntax().clone())
     } else {
@@ -350,9 +371,7 @@ fn function_declaration(node: &ast::Fn, needs_whitespace: bool) -> String {
         .map_or(end, |f| f.text_range().start());
 
     let len = end - start;
-    let range = TextRange::new(0.into(), len);
-
-    let syntax = node.text().slice(range).to_string();
+    let syntax = node.text().slice(..len).to_string();
 
     syntax.trim_end().to_owned()
 }
@@ -1163,4 +1182,104 @@ impl Foo for Test {
 "#,
         );
     }
+
+    #[test]
+    fn includes_gat_generics() {
+        check_edit(
+            "type Ty",
+            r#"
+trait Tr<'b> {
+    type Ty<'a: 'b, T: Copy, const C: usize>;
+}
+
+impl<'b> Tr<'b> for () {
+    $0
+}
+"#,
+            r#"
+trait Tr<'b> {
+    type Ty<'a: 'b, T: Copy, const C: usize>;
+}
+
+impl<'b> Tr<'b> for () {
+    type Ty<'a: 'b, T: Copy, const C: usize> = $0;
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn strips_comments() {
+        check_edit(
+            "fn func",
+            r#"
+trait Tr {
+    /// docs
+    #[attr]
+    fn func();
+}
+impl Tr for () {
+    $0
+}
+"#,
+            r#"
+trait Tr {
+    /// docs
+    #[attr]
+    fn func();
+}
+impl Tr for () {
+    fn func() {
+    $0
+}
+}
+"#,
+        );
+        check_edit(
+            "const C",
+            r#"
+trait Tr {
+    /// docs
+    #[attr]
+    const C: usize;
+}
+impl Tr for () {
+    $0
+}
+"#,
+            r#"
+trait Tr {
+    /// docs
+    #[attr]
+    const C: usize;
+}
+impl Tr for () {
+    const C: usize = $0;
+}
+"#,
+        );
+        check_edit(
+            "type Item",
+            r#"
+trait Tr {
+    /// docs
+    #[attr]
+    type Item;
+}
+impl Tr for () {
+    $0
+}
+"#,
+            r#"
+trait Tr {
+    /// docs
+    #[attr]
+    type Item;
+}
+impl Tr for () {
+    type Item = $0;
+}
+"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index 04111ec7efa..c142a7305f9 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -681,9 +681,13 @@ fn classify_name_ref(
                     ast::Item::ExternBlock(it) => it.extern_item_list().is_none(),
                     ast::Item::Fn(it) => it.body().is_none(),
                     ast::Item::Impl(it) => it.assoc_item_list().is_none(),
-                    ast::Item::Module(it) => it.item_list().is_none(),
+                    ast::Item::Module(it) => {
+                        it.item_list().is_none() && it.semicolon_token().is_none()
+                    }
                     ast::Item::Static(it) => it.body().is_none(),
-                    ast::Item::Struct(it) => it.field_list().is_none(),
+                    ast::Item::Struct(it) => {
+                        it.field_list().is_none() && it.semicolon_token().is_none()
+                    }
                     ast::Item::Trait(it) => it.assoc_item_list().is_none(),
                     ast::Item::TypeAlias(it) => it.ty().is_none(),
                     ast::Item::Union(it) => it.record_field_list().is_none(),
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
index 5076c6e86ca..8ed6cb3cf86 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
@@ -245,3 +245,35 @@ impl Test for () {
         "#]],
     );
 }
+
+#[test]
+fn after_unit_struct() {
+    check(
+        r#"struct S; f$0"#,
+        expect![[r#"
+            ma makro!(…)           macro_rules! makro
+            md module
+            kw const
+            kw crate::
+            kw enum
+            kw extern
+            kw fn
+            kw impl
+            kw mod
+            kw pub
+            kw pub(crate)
+            kw pub(super)
+            kw self::
+            kw static
+            kw struct
+            kw trait
+            kw type
+            kw union
+            kw unsafe
+            kw use
+            sn macro_rules
+            sn tfn (Test function)
+            sn tmod (Test module)
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
index cf0bcd5c96b..f48cce58c6e 100644
--- a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/line_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/line_index.rs
index 75d49ff2fd7..1b8f56187a0 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/line_index.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/line_index.rs
@@ -58,8 +58,11 @@ impl LineIndex {
         let mut utf16_lines = NoHashHashMap::default();
         let mut utf16_chars = Vec::new();
 
-        let mut newlines = vec![0.into()];
-        let mut curr_row @ mut curr_col = 0.into();
+        let mut newlines = Vec::with_capacity(16);
+        newlines.push(TextSize::from(0));
+
+        let mut curr_row = 0.into();
+        let mut curr_col = 0.into();
         let mut line = 0;
         for c in text.chars() {
             let c_len = TextSize::of(c);
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs
index ac6c6e8feee..313346ee131 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs
@@ -104,6 +104,11 @@ pub fn parse_format_exprs(input: &str) -> Result<(String, Vec<Arg>), ()> {
                 extracted_expressions.push(Arg::Placeholder);
                 state = State::NotArg;
             }
+            (State::MaybeArg, ':') => {
+                output.push(chr);
+                extracted_expressions.push(Arg::Placeholder);
+                state = State::FormatOpts;
+            }
             (State::MaybeArg, _) => {
                 if matches!(chr, '\\' | '$') {
                     current_expr.push('\\');
@@ -118,44 +123,41 @@ pub fn parse_format_exprs(input: &str) -> Result<(String, Vec<Arg>), ()> {
                     state = State::Expr;
                 }
             }
-            (State::Ident | State::Expr, '}') => {
-                if inexpr_open_count == 0 {
-                    output.push(chr);
-
-                    if matches!(state, State::Expr) {
-                        extracted_expressions.push(Arg::Expr(current_expr.trim().into()));
-                    } else {
-                        extracted_expressions.push(Arg::Ident(current_expr.trim().into()));
-                    }
-
-                    current_expr = String::new();
-                    state = State::NotArg;
-                } else {
-                    // We're closing one brace met before inside of the expression.
-                    current_expr.push(chr);
-                    inexpr_open_count -= 1;
-                }
-            }
             (State::Ident | State::Expr, ':') if matches!(chars.peek(), Some(':')) => {
                 // path separator
                 state = State::Expr;
                 current_expr.push_str("::");
                 chars.next();
             }
-            (State::Ident | State::Expr, ':') => {
+            (State::Ident | State::Expr, ':' | '}') => {
                 if inexpr_open_count == 0 {
-                    // We're outside of braces, thus assume that it's a specifier, like "{Some(value):?}"
-                    output.push(chr);
+                    let trimmed = current_expr.trim();
 
-                    if matches!(state, State::Expr) {
-                        extracted_expressions.push(Arg::Expr(current_expr.trim().into()));
+                    // if the expression consists of a single number, like "0" or "12", it can refer to
+                    // format args in the order they are specified.
+                    // see: https://doc.rust-lang.org/std/fmt/#positional-parameters
+                    if trimmed.chars().fold(true, |only_num, c| c.is_ascii_digit() && only_num) {
+                        output.push_str(trimmed);
+                    } else if matches!(state, State::Expr) {
+                        extracted_expressions.push(Arg::Expr(trimmed.into()));
                     } else {
-                        extracted_expressions.push(Arg::Ident(current_expr.trim().into()));
+                        extracted_expressions.push(Arg::Ident(trimmed.into()));
                     }
 
-                    current_expr = String::new();
-                    state = State::FormatOpts;
-                } else {
+                    output.push(chr);
+                    current_expr.clear();
+                    state = if chr == ':' {
+                        State::FormatOpts
+                    } else if chr == '}' {
+                        State::NotArg
+                    } else {
+                        unreachable!()
+                    };
+                } else if chr == '}' {
+                    // We're closing one brace met before inside of the expression.
+                    current_expr.push(chr);
+                    inexpr_open_count -= 1;
+                } else if chr == ':' {
                     // We're inside of braced expression, assume that it's a struct field name/value delimiter.
                     current_expr.push(chr);
                 }
@@ -219,6 +221,10 @@ mod tests {
             ("{expr} is {2 + 2}", expect![["{} is {}; expr, 2 + 2"]]),
             ("{expr:?}", expect![["{:?}; expr"]]),
             ("{expr:1$}", expect![[r"{:1\$}; expr"]]),
+            ("{:1$}", expect![[r"{:1\$}; $1"]]),
+            ("{:>padding$}", expect![[r"{:>padding\$}; $1"]]),
+            ("{}, {}, {0}", expect![[r"{}, {}, {0}; $1, $2"]]),
+            ("{}, {}, {0:b}", expect![[r"{}, {}, {0:b}; $1, $2"]]),
             ("{$0}", expect![[r"{}; \$0"]]),
             ("{malformed", expect![["-"]]),
             ("malformed}", expect![["-"]]),
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
index e1d146f4ee5..7e9a1125d75 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
index 43ff4ed5a6c..870c78d1f1e 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
@@ -5,10 +5,7 @@ use crate::{Diagnostic, DiagnosticsContext};
 // This diagnostic is shown for macro expansion errors.
 pub(crate) fn macro_error(ctx: &DiagnosticsContext<'_>, d: &hir::MacroError) -> Diagnostic {
     // Use more accurate position if available.
-    let display_range = d
-        .precise_location
-        .unwrap_or_else(|| ctx.sema.diagnostics_display_range(d.node.clone()).range);
-
+    let display_range = ctx.resolve_precise_location(&d.node, d.precise_location);
     Diagnostic::new("macro-error", d.message.clone(), display_range).experimental()
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs
index a80299106bd..d8f2a9de981 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs
@@ -268,12 +268,12 @@ fn main() {
     foo::Foo { bar: 3, $0baz: false};
 }
 //- /foo.rs
-struct Foo {
+pub struct Foo {
     bar: i32
 }
 "#,
             r#"
-struct Foo {
+pub struct Foo {
     bar: i32,
     pub(crate) baz: bool
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs
index 4b43124757f..87531f4acfb 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs
@@ -9,10 +9,7 @@ pub(crate) fn unresolved_macro_call(
     d: &hir::UnresolvedMacroCall,
 ) -> Diagnostic {
     // Use more accurate position if available.
-    let display_range = d
-        .precise_location
-        .unwrap_or_else(|| ctx.sema.diagnostics_display_range(d.macro_call.clone()).range);
-
+    let display_range = ctx.resolve_precise_location(&d.macro_call, d.precise_location);
     let bang = if d.is_bang { "!" } else { "" };
     Diagnostic::new(
         "unresolved-macro-call",
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
index 760f51f9049..23818d883f7 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
@@ -1,5 +1,4 @@
 use hir::db::DefDatabase;
-use syntax::NodeOrToken;
 
 use crate::{Diagnostic, DiagnosticsContext, Severity};
 
@@ -19,16 +18,7 @@ pub(crate) fn unresolved_proc_macro(
     proc_attr_macros_enabled: bool,
 ) -> Diagnostic {
     // Use more accurate position if available.
-    let display_range = (|| {
-        let precise_location = d.precise_location?;
-        let root = ctx.sema.parse_or_expand(d.node.file_id)?;
-        match root.covering_element(precise_location) {
-            NodeOrToken::Node(it) => Some(ctx.sema.original_range(&it)),
-            NodeOrToken::Token(it) => d.node.with_value(it).original_file_range_opt(ctx.sema.db),
-        }
-    })()
-    .unwrap_or_else(|| ctx.sema.diagnostics_display_range(d.node.clone()))
-    .range;
+    let display_range = ctx.resolve_precise_location(&d.node, d.precise_location);
 
     let config_enabled = match d.kind {
         hir::MacroKind::Attr => proc_macros_enabled && proc_attr_macros_enabled,
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/useless_braces.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/useless_braces.rs
index 8b9330e0401..289ed0458c6 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/useless_braces.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/useless_braces.rs
@@ -71,9 +71,9 @@ use a;
 use a::{c, d::e};
 
 mod a {
-    mod c {}
-    mod d {
-        mod e {}
+    pub mod c {}
+    pub mod d {
+        pub mod e {}
     }
 }
 "#,
@@ -87,9 +87,9 @@ use a::{
 };
 
 mod a {
-    mod c {}
-    mod d {
-        mod e {}
+    pub mod c {}
+    pub mod d {
+        pub mod e {}
     }
 }
 "#,
@@ -116,11 +116,11 @@ use b;
         );
         check_fix(
             r#"
-mod a { mod c {} }
+mod a { pub mod c {} }
 use a::{c$0};
 "#,
             r#"
-mod a { mod c {} }
+mod a { pub mod c {} }
 use a::c;
 "#,
         );
@@ -136,11 +136,11 @@ use a;
         );
         check_fix(
             r#"
-mod a { mod c {} mod d { mod e {} } }
+mod a { pub mod c {} pub mod d { pub mod e {} } }
 use a::{c, d::{e$0}};
 "#,
             r#"
-mod a { mod c {} mod d { mod e {} } }
+mod a { pub mod c {} pub mod d { pub mod e {} } }
 use a::{c, d::e};
 "#,
         );
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
index ae299f05841..d81e36a1f86 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
@@ -182,6 +182,28 @@ struct DiagnosticsContext<'a> {
     resolve: &'a AssistResolveStrategy,
 }
 
+impl<'a> DiagnosticsContext<'a> {
+    fn resolve_precise_location(
+        &self,
+        node: &InFile<SyntaxNodePtr>,
+        precise_location: Option<TextRange>,
+    ) -> TextRange {
+        let sema = &self.sema;
+        (|| {
+            let precise_location = precise_location?;
+            let root = sema.parse_or_expand(node.file_id)?;
+            match root.covering_element(precise_location) {
+                syntax::NodeOrToken::Node(it) => Some(sema.original_range(&it)),
+                syntax::NodeOrToken::Token(it) => {
+                    node.with_value(it).original_file_range_opt(sema.db)
+                }
+            }
+        })()
+        .unwrap_or_else(|| sema.diagnostics_display_range(node.clone()))
+        .range
+    }
+}
+
 pub fn diagnostics(
     db: &RootDatabase,
     config: &DiagnosticsConfig,
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
index 4baf786c455..7be62a8d9ff 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
@@ -5,7 +5,7 @@ description = "Structural search and replace of Rust code"
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-lang/rust-analyzer"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/ide/Cargo.toml b/src/tools/rust-analyzer/crates/ide/Cargo.toml
index 712459a7ee9..73f202630f1 100644
--- a/src/tools/rust-analyzer/crates/ide/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
index f97c67b144a..43f7a529bc2 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -289,10 +289,10 @@ mod b;
 enum E { X(Foo$0) }
 
 //- /a.rs
-struct Foo;
-     //^^^
+pub struct Foo;
+         //^^^
 //- /b.rs
-struct Foo;
+pub struct Foo;
 "#,
         );
     }
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 3687b597fc6..838fb18c3d5 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -119,7 +119,14 @@ pub(crate) fn hover(
         });
     }
 
-    let in_attr = matches!(original_token.parent().and_then(ast::TokenTree::cast), Some(tt) if tt.syntax().ancestors().any(|it| ast::Meta::can_cast(it.kind())));
+    let in_attr = original_token
+        .parent_ancestors()
+        .filter_map(ast::Item::cast)
+        .any(|item| sema.is_attr_macro_call(&item))
+        && !matches!(
+            original_token.parent().and_then(ast::TokenTree::cast),
+            Some(tt) if tt.syntax().ancestors().any(|it| ast::Meta::can_cast(it.kind()))
+        );
     // prefer descending the same token kind in attribute expansions, in normal macros text
     // equivalency is more important
     let descended = if in_attr {
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
index 34d8bf67a30..37384c4e7e0 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
@@ -1,7 +1,10 @@
 use std::fmt;
 
 use either::Either;
-use hir::{known, Callable, HasVisibility, HirDisplay, Mutability, Semantics, TypeInfo};
+use hir::{
+    known, Adjust, AutoBorrow, Callable, HasVisibility, HirDisplay, Mutability, OverloadedDeref,
+    PointerCast, Safety, Semantics, TypeInfo,
+};
 use ide_db::{
     base_db::FileRange, famous_defs::FamousDefs, syntax_helpers::node_ext::walk_ty, FxHashMap,
     RootDatabase,
@@ -22,7 +25,7 @@ pub struct InlayHintsConfig {
     pub type_hints: bool,
     pub parameter_hints: bool,
     pub chaining_hints: bool,
-    pub reborrow_hints: ReborrowHints,
+    pub adjustment_hints: AdjustmentHints,
     pub closure_return_type_hints: ClosureReturnTypeHints,
     pub binding_mode_hints: bool,
     pub lifetime_elision_hints: LifetimeElisionHints,
@@ -48,9 +51,9 @@ pub enum LifetimeElisionHints {
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
-pub enum ReborrowHints {
+pub enum AdjustmentHints {
     Always,
-    MutableOnly,
+    ReborrowOnly,
     Never,
 }
 
@@ -61,7 +64,8 @@ pub enum InlayKind {
     ClosingBraceHint,
     ClosureReturnTypeHint,
     GenericParamListHint,
-    ImplicitReborrowHint,
+    AdjustmentHint,
+    AdjustmentHintClosingParenthesis,
     LifetimeHint,
     ParameterHint,
     TypeHint,
@@ -115,6 +119,12 @@ impl From<String> for InlayHintLabel {
     }
 }
 
+impl From<&str> for InlayHintLabel {
+    fn from(s: &str) -> Self {
+        Self { parts: vec![InlayHintLabelPart { text: s.into(), linked_location: None }] }
+    }
+}
+
 impl fmt::Display for InlayHintLabel {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{}", self.parts.iter().map(|part| &part.text).format(""))
@@ -180,7 +190,7 @@ impl fmt::Debug for InlayHintLabelPart {
 pub(crate) fn inlay_hints(
     db: &RootDatabase,
     file_id: FileId,
-    range_limit: Option<FileRange>,
+    range_limit: Option<TextRange>,
     config: &InlayHintsConfig,
 ) -> Vec<InlayHint> {
     let _p = profile::span("inlay_hints");
@@ -195,7 +205,7 @@ pub(crate) fn inlay_hints(
 
         let hints = |node| hints(&mut acc, &famous_defs, config, file_id, node);
         match range_limit {
-            Some(FileRange { range, .. }) => match file.covering_element(range) {
+            Some(range) => match file.covering_element(range) {
                 NodeOrToken::Token(_) => return acc,
                 NodeOrToken::Node(n) => n
                     .descendants()
@@ -221,6 +231,7 @@ fn hints(
         match node {
             ast::Expr(expr) => {
                 chaining_hints(hints, sema, &famous_defs, config, file_id, &expr);
+                adjustment_hints(hints, sema, config, &expr);
                 match expr {
                     ast::Expr::CallExpr(it) => param_name_hints(hints, sema, config, ast::Expr::from(it)),
                     ast::Expr::MethodCallExpr(it) => {
@@ -229,7 +240,7 @@ fn hints(
                     ast::Expr::ClosureExpr(it) => closure_ret_hints(hints, sema, &famous_defs, config, file_id, it),
                     // We could show reborrows for all expressions, but usually that is just noise to the user
                     // and the main point here is to show why "moving" a mutable reference doesn't necessarily move it
-                    ast::Expr::PathExpr(_) => reborrow_hints(hints, sema, config, &expr),
+                    // ast::Expr::PathExpr(_) => reborrow_hints(hints, sema, config, &expr),
                     _ => None,
                 }
             },
@@ -617,30 +628,95 @@ fn closure_ret_hints(
     Some(())
 }
 
-fn reborrow_hints(
+fn adjustment_hints(
     acc: &mut Vec<InlayHint>,
     sema: &Semantics<'_, RootDatabase>,
     config: &InlayHintsConfig,
     expr: &ast::Expr,
 ) -> Option<()> {
-    if config.reborrow_hints == ReborrowHints::Never {
+    if config.adjustment_hints == AdjustmentHints::Never {
+        return None;
+    }
+
+    if let ast::Expr::ParenExpr(_) = expr {
+        // These inherit from the inner expression which would result in duplicate hints
         return None;
     }
 
+    let parent = expr.syntax().parent().and_then(ast::Expr::cast);
     let descended = sema.descend_node_into_attributes(expr.clone()).pop();
     let desc_expr = descended.as_ref().unwrap_or(expr);
-    let mutability = sema.is_implicit_reborrow(desc_expr)?;
-    let label = match mutability {
-        hir::Mutability::Shared if config.reborrow_hints != ReborrowHints::MutableOnly => "&*",
-        hir::Mutability::Mut => "&mut *",
-        _ => return None,
+    let adjustments = sema.expr_adjustments(desc_expr).filter(|it| !it.is_empty())?;
+    let needs_parens = match parent {
+        Some(parent) => {
+            match parent {
+                ast::Expr::AwaitExpr(_)
+                | ast::Expr::CallExpr(_)
+                | ast::Expr::CastExpr(_)
+                | ast::Expr::FieldExpr(_)
+                | ast::Expr::MethodCallExpr(_)
+                | ast::Expr::TryExpr(_) => true,
+                // FIXME: shorthands need special casing, though not sure if adjustments are even valid there
+                ast::Expr::RecordExpr(_) => false,
+                ast::Expr::IndexExpr(index) => index.base().as_ref() == Some(expr),
+                _ => false,
+            }
+        }
+        None => false,
     };
-    acc.push(InlayHint {
-        range: expr.syntax().text_range(),
-        kind: InlayKind::ImplicitReborrowHint,
-        label: label.to_string().into(),
-        tooltip: Some(InlayTooltip::String("Compiler inserted reborrow".into())),
-    });
+    if needs_parens {
+        acc.push(InlayHint {
+            range: expr.syntax().text_range(),
+            kind: InlayKind::AdjustmentHint,
+            label: "(".into(),
+            tooltip: None,
+        });
+    }
+    for adjustment in adjustments.into_iter().rev() {
+        // FIXME: Add some nicer tooltips to each of these
+        let text = match adjustment {
+            Adjust::NeverToAny if config.adjustment_hints == AdjustmentHints::Always => {
+                "<never-to-any>"
+            }
+            Adjust::Deref(None) => "*",
+            Adjust::Deref(Some(OverloadedDeref(Mutability::Mut))) => "*",
+            Adjust::Deref(Some(OverloadedDeref(Mutability::Shared))) => "*",
+            Adjust::Borrow(AutoBorrow::Ref(Mutability::Shared)) => "&",
+            Adjust::Borrow(AutoBorrow::Ref(Mutability::Mut)) => "&mut ",
+            Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Shared)) => "&raw const ",
+            Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Mut)) => "&raw mut ",
+            // some of these could be represented via `as` casts, but that's not too nice and
+            // handling everything as a prefix expr makes the `(` and `)` insertion easier
+            Adjust::Pointer(cast) if config.adjustment_hints == AdjustmentHints::Always => {
+                match cast {
+                    PointerCast::ReifyFnPointer => "<fn-item-to-fn-pointer>",
+                    PointerCast::UnsafeFnPointer => "<safe-fn-pointer-to-unsafe-fn-pointer>",
+                    PointerCast::ClosureFnPointer(Safety::Unsafe) => {
+                        "<closure-to-unsafe-fn-pointer>"
+                    }
+                    PointerCast::ClosureFnPointer(Safety::Safe) => "<closure-to-fn-pointer>",
+                    PointerCast::MutToConstPointer => "<mut-ptr-to-const-ptr>",
+                    PointerCast::ArrayToPointer => "<array-ptr-to-element-ptr>",
+                    PointerCast::Unsize => "<unsize>",
+                }
+            }
+            _ => continue,
+        };
+        acc.push(InlayHint {
+            range: expr.syntax().text_range(),
+            kind: InlayKind::AdjustmentHint,
+            label: text.into(),
+            tooltip: None,
+        });
+    }
+    if needs_parens {
+        acc.push(InlayHint {
+            range: expr.syntax().text_range(),
+            kind: InlayKind::AdjustmentHintClosingParenthesis,
+            label: ")".into(),
+            tooltip: None,
+        });
+    }
     Some(())
 }
 
@@ -1213,12 +1289,11 @@ fn get_callable(
 #[cfg(test)]
 mod tests {
     use expect_test::{expect, Expect};
-    use ide_db::base_db::FileRange;
     use itertools::Itertools;
     use syntax::{TextRange, TextSize};
     use test_utils::extract_annotations;
 
-    use crate::inlay_hints::ReborrowHints;
+    use crate::inlay_hints::AdjustmentHints;
     use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints};
 
     use super::ClosureReturnTypeHints;
@@ -1230,7 +1305,7 @@ mod tests {
         chaining_hints: false,
         lifetime_elision_hints: LifetimeElisionHints::Never,
         closure_return_type_hints: ClosureReturnTypeHints::Never,
-        reborrow_hints: ReborrowHints::Always,
+        adjustment_hints: AdjustmentHints::Never,
         binding_mode_hints: false,
         hide_named_constructor_hints: false,
         hide_closure_initialization_hints: false,
@@ -1242,7 +1317,6 @@ mod tests {
         type_hints: true,
         parameter_hints: true,
         chaining_hints: true,
-        reborrow_hints: ReborrowHints::Always,
         closure_return_type_hints: ClosureReturnTypeHints::WithBlock,
         binding_mode_hints: true,
         lifetime_elision_hints: LifetimeElisionHints::Always,
@@ -1838,10 +1912,7 @@ fn main() {
             .inlay_hints(
                 &InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG },
                 file_id,
-                Some(FileRange {
-                    file_id,
-                    range: TextRange::new(TextSize::from(500), TextSize::from(600)),
-                }),
+                Some(TextRange::new(TextSize::from(500), TextSize::from(600))),
             )
             .unwrap();
         let actual =
@@ -2846,48 +2917,6 @@ impl () {
     }
 
     #[test]
-    fn hints_implicit_reborrow() {
-        check_with_config(
-            InlayHintsConfig {
-                reborrow_hints: ReborrowHints::Always,
-                parameter_hints: true,
-                ..DISABLED_CONFIG
-            },
-            r#"
-fn __() {
-    let unique = &mut ();
-    let r_mov = unique;
-    let foo: &mut _ = unique;
-                    //^^^^^^ &mut *
-    ref_mut_id(unique);
-             //^^^^^^ mut_ref
-             //^^^^^^ &mut *
-    let shared = ref_id(unique);
-                      //^^^^^^ shared_ref
-                      //^^^^^^ &*
-    let mov = shared;
-    let r_mov: &_ = shared;
-    ref_id(shared);
-         //^^^^^^ shared_ref
-
-    identity(unique);
-    identity(shared);
-}
-fn identity<T>(t: T) -> T {
-    t
-}
-fn ref_mut_id(mut_ref: &mut ()) -> &mut () {
-    mut_ref
-  //^^^^^^^ &mut *
-}
-fn ref_id(shared_ref: &()) -> &() {
-    shared_ref
-}
-"#,
-        );
-    }
-
-    #[test]
     fn hints_binding_modes() {
         check_with_config(
             InlayHintsConfig { binding_mode_hints: true, ..DISABLED_CONFIG },
@@ -2994,4 +3023,76 @@ fn f() {
 "#,
         );
     }
+
+    #[test]
+    fn adjustment_hints() {
+        check_with_config(
+            InlayHintsConfig { adjustment_hints: AdjustmentHints::Always, ..DISABLED_CONFIG },
+            r#"
+//- minicore: coerce_unsized
+fn main() {
+    let _: u32         = loop {};
+                       //^^^^^^^<never-to-any>
+    let _: &u32        = &mut 0;
+                       //^^^^^^&
+                       //^^^^^^*
+    let _: &mut u32    = &mut 0;
+                       //^^^^^^&mut $
+                       //^^^^^^*
+    let _: *const u32  = &mut 0;
+                       //^^^^^^&raw const $
+                       //^^^^^^*
+    let _: *mut u32    = &mut 0;
+                       //^^^^^^&raw mut $
+                       //^^^^^^*
+    let _: fn()        = main;
+                       //^^^^<fn-item-to-fn-pointer>
+    let _: unsafe fn() = main;
+                       //^^^^<safe-fn-pointer-to-unsafe-fn-pointer>
+                       //^^^^<fn-item-to-fn-pointer>
+    let _: unsafe fn() = main as fn();
+                       //^^^^^^^^^^^^<safe-fn-pointer-to-unsafe-fn-pointer>
+    let _: fn()        = || {};
+                       //^^^^^<closure-to-fn-pointer>
+    let _: unsafe fn() = || {};
+                       //^^^^^<closure-to-unsafe-fn-pointer>
+    let _: *const u32  = &mut 0u32 as *mut u32;
+                       //^^^^^^^^^^^^^^^^^^^^^<mut-ptr-to-const-ptr>
+    let _: &mut [_]    = &mut [0; 0];
+                       //^^^^^^^^^^^<unsize>
+                       //^^^^^^^^^^^&mut $
+                       //^^^^^^^^^^^*
+
+    Struct.consume();
+    Struct.by_ref();
+  //^^^^^^(
+  //^^^^^^&
+  //^^^^^^)
+    Struct.by_ref_mut();
+  //^^^^^^(
+  //^^^^^^&mut $
+  //^^^^^^)
+
+    (&Struct).consume();
+   //^^^^^^^*
+    (&Struct).by_ref();
+
+    (&mut Struct).consume();
+   //^^^^^^^^^^^*
+    (&mut Struct).by_ref();
+   //^^^^^^^^^^^&
+   //^^^^^^^^^^^*
+    (&mut Struct).by_ref_mut();
+}
+
+#[derive(Copy, Clone)]
+struct Struct;
+impl Struct {
+    fn consume(self) {}
+    fn by_ref(&self) {}
+    fn by_ref_mut(&mut self) {}
+}
+"#,
+        )
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index 416817ca0b4..7402e86f36f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -81,8 +81,8 @@ pub use crate::{
     highlight_related::{HighlightRelatedConfig, HighlightedRange},
     hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult},
     inlay_hints::{
-        ClosureReturnTypeHints, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind,
-        InlayTooltip, LifetimeElisionHints, ReborrowHints,
+        AdjustmentHints, ClosureReturnTypeHints, InlayHint, InlayHintLabel, InlayHintsConfig,
+        InlayKind, InlayTooltip, LifetimeElisionHints,
     },
     join_lines::JoinLinesConfig,
     markup::Markup,
@@ -367,7 +367,7 @@ impl Analysis {
         &self,
         config: &InlayHintsConfig,
         file_id: FileId,
-        range: Option<FileRange>,
+        range: Option<TextRange>,
     ) -> Cancellable<Vec<InlayHint>> {
         self.with_db(|db| inlay_hints::inlay_hints(db, file_id, range, config))
     }
diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
index 07d117aff10..fcbf6d8e58c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
@@ -1,9 +1,9 @@
 //! This module generates [moniker](https://microsoft.github.io/language-server-protocol/specifications/lsif/0.6.0/specification/#exportsImports)
 //! for LSIF and LSP.
 
-use hir::{db::DefDatabase, AsAssocItem, AssocItemContainer, Crate, Name, Semantics};
+use hir::{AsAssocItem, AssocItemContainer, Crate, Name, Semantics};
 use ide_db::{
-    base_db::{CrateOrigin, FileId, FileLoader, FilePosition, LangCrateOrigin},
+    base_db::{CrateOrigin, FilePosition, LangCrateOrigin},
     defs::{Definition, IdentClass},
     helpers::pick_best_token,
     RootDatabase,
@@ -11,7 +11,7 @@ use ide_db::{
 use itertools::Itertools;
 use syntax::{AstNode, SyntaxKind::*, T};
 
-use crate::{doc_links::token_as_doc_comment, RangeInfo};
+use crate::{doc_links::token_as_doc_comment, parent_module::crates_for, RangeInfo};
 
 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub enum MonikerDescriptorKind {
@@ -77,25 +77,13 @@ pub struct PackageInformation {
     pub version: Option<String>,
 }
 
-pub(crate) fn crate_for_file(db: &RootDatabase, file_id: FileId) -> Option<Crate> {
-    for &krate in db.relevant_crates(file_id).iter() {
-        let crate_def_map = db.crate_def_map(krate);
-        for (_, data) in crate_def_map.modules() {
-            if data.origin.file_id() == Some(file_id) {
-                return Some(krate.into());
-            }
-        }
-    }
-    None
-}
-
 pub(crate) fn moniker(
     db: &RootDatabase,
     FilePosition { file_id, offset }: FilePosition,
 ) -> Option<RangeInfo<Vec<MonikerResult>>> {
     let sema = &Semantics::new(db);
     let file = sema.parse(file_id).syntax().clone();
-    let current_crate = crate_for_file(db, file_id)?;
+    let current_crate: hir::Crate = crates_for(db, file_id).pop()?.into();
     let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
         IDENT
         | INT_NUMBER
diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs
index e942413c110..0f758cfa2d3 100644
--- a/src/tools/rust-analyzer/crates/ide/src/references.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/references.rs
@@ -16,6 +16,7 @@ use ide_db::{
     search::{ReferenceCategory, SearchScope, UsageSearchResult},
     RootDatabase,
 };
+use itertools::Itertools;
 use stdx::hash::NoHashHashMap;
 use syntax::{
     algo::find_node_at_offset,
@@ -86,6 +87,7 @@ pub(crate) fn find_all_refs(
                         file_id,
                         refs.into_iter()
                             .map(|file_ref| (file_ref.range, file_ref.category))
+                            .unique()
                             .collect(),
                     )
                 })
diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
index 7486b20293a..e7412d27faf 100644
--- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
@@ -1345,5 +1345,36 @@ fn f<F: FnOnce(u8, u16) -> i32>(f: F) {
                  ^^  ---
             "#]],
         );
+        check(
+            r#"
+fn f<T, F: FnOnce(&T, u16) -> &T>(f: F) {
+    f($0)
+}
+"#,
+            expect![[r#"
+                (&T, u16) -> &T
+                 ^^  ---
+            "#]],
+        );
+    }
+
+    #[test]
+    fn regression_13579() {
+        check(
+            r#"
+fn f() {
+    take(2)($0);
+}
+
+fn take<C, Error>(
+    count: C
+) -> impl Fn() -> C  {
+    move || count
+}
+"#,
+            expect![[r#"
+                () -> i32
+            "#]],
+        );
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
index 27ad1a948d1..2380cf7381c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
@@ -13,7 +13,8 @@ use syntax::{AstNode, SyntaxKind::*, SyntaxToken, TextRange, T};
 
 use crate::{
     hover::hover_for_definition,
-    moniker::{crate_for_file, def_to_moniker, MonikerResult},
+    moniker::{def_to_moniker, MonikerResult},
+    parent_module::crates_for,
     Analysis, Fold, HoverConfig, HoverDocFormat, HoverResult, InlayHint, InlayHintsConfig,
     TryToNav,
 };
@@ -99,7 +100,7 @@ fn all_modules(db: &dyn HirDatabase) -> Vec<Module> {
 
 impl StaticIndex<'_> {
     fn add_file(&mut self, file_id: FileId) {
-        let current_crate = crate_for_file(self.db, file_id);
+        let current_crate = crates_for(self.db, file_id).pop().map(Into::into);
         let folds = self.analysis.folding_ranges(file_id).unwrap();
         let inlay_hints = self
             .analysis
@@ -111,7 +112,7 @@ impl StaticIndex<'_> {
                     chaining_hints: true,
                     closure_return_type_hints: crate::ClosureReturnTypeHints::WithBlock,
                     lifetime_elision_hints: crate::LifetimeElisionHints::Never,
-                    reborrow_hints: crate::ReborrowHints::Never,
+                    adjustment_hints: crate::AdjustmentHints::Never,
                     hide_named_constructor_hints: false,
                     hide_closure_initialization_hints: false,
                     param_names_for_lifetime_elision_hints: false,
diff --git a/src/tools/rust-analyzer/crates/limit/Cargo.toml b/src/tools/rust-analyzer/crates/limit/Cargo.toml
index 893db436d8b..3536f73da73 100644
--- a/src/tools/rust-analyzer/crates/limit/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/limit/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [features]
 tracking = []
diff --git a/src/tools/rust-analyzer/crates/mbe/Cargo.toml b/src/tools/rust-analyzer/crates/mbe/Cargo.toml
index 13cd8901031..bce2fc9a70e 100644
--- a/src/tools/rust-analyzer/crates/mbe/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/mbe/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
index e4c56565b92..cf53c16726b 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
@@ -12,6 +12,9 @@ use tt::buffer::{Cursor, TokenBuffer};
 
 use crate::{to_parser_input::to_parser_input, tt_iter::TtIter, TokenMap};
 
+#[cfg(test)]
+mod tests;
+
 /// Convert the syntax node to a `TokenTree` (what macro
 /// will consume).
 pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> (tt::Subtree, TokenMap) {
@@ -35,7 +38,7 @@ pub fn syntax_node_to_token_tree_with_modifications(
     append: FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
 ) -> (tt::Subtree, TokenMap, u32) {
     let global_offset = node.text_range().start();
-    let mut c = Convertor::new(node, global_offset, existing_token_map, next_id, replace, append);
+    let mut c = Converter::new(node, global_offset, existing_token_map, next_id, replace, append);
     let subtree = convert_tokens(&mut c);
     c.id_alloc.map.shrink_to_fit();
     always!(c.replace.is_empty(), "replace: {:?}", c.replace);
@@ -100,7 +103,7 @@ pub fn parse_to_token_tree(text: &str) -> Option<(tt::Subtree, TokenMap)> {
         return None;
     }
 
-    let mut conv = RawConvertor {
+    let mut conv = RawConverter {
         lexed,
         pos: 0,
         id_alloc: TokenIdAlloc {
@@ -148,7 +151,7 @@ pub fn parse_exprs_with_sep(tt: &tt::Subtree, sep: char) -> Vec<tt::Subtree> {
     res
 }
 
-fn convert_tokens<C: TokenConvertor>(conv: &mut C) -> tt::Subtree {
+fn convert_tokens<C: TokenConverter>(conv: &mut C) -> tt::Subtree {
     struct StackEntry {
         subtree: tt::Subtree,
         idx: usize,
@@ -228,7 +231,7 @@ fn convert_tokens<C: TokenConvertor>(conv: &mut C) -> tt::Subtree {
             }
 
             let spacing = match conv.peek().map(|next| next.kind(conv)) {
-                Some(kind) if !kind.is_trivia() => tt::Spacing::Joint,
+                Some(kind) if is_single_token_op(kind) => tt::Spacing::Joint,
                 _ => tt::Spacing::Alone,
             };
             let char = match token.to_char(conv) {
@@ -307,6 +310,35 @@ fn convert_tokens<C: TokenConvertor>(conv: &mut C) -> tt::Subtree {
     }
 }
 
+fn is_single_token_op(kind: SyntaxKind) -> bool {
+    matches!(
+        kind,
+        EQ | L_ANGLE
+            | R_ANGLE
+            | BANG
+            | AMP
+            | PIPE
+            | TILDE
+            | AT
+            | DOT
+            | COMMA
+            | SEMICOLON
+            | COLON
+            | POUND
+            | DOLLAR
+            | QUESTION
+            | PLUS
+            | MINUS
+            | STAR
+            | SLASH
+            | PERCENT
+            | CARET
+            // LIFETIME_IDENT will be split into a sequence of `'` (a single quote) and an
+            // identifier.
+            | LIFETIME_IDENT
+    )
+}
+
 /// Returns the textual content of a doc comment block as a quoted string
 /// That is, strips leading `///` (or `/**`, etc)
 /// and strips the ending `*/`
@@ -425,8 +457,8 @@ impl TokenIdAlloc {
     }
 }
 
-/// A raw token (straight from lexer) convertor
-struct RawConvertor<'a> {
+/// A raw token (straight from lexer) converter
+struct RawConverter<'a> {
     lexed: parser::LexedStr<'a>,
     pos: usize,
     id_alloc: TokenIdAlloc,
@@ -442,7 +474,7 @@ trait SrcToken<Ctx>: std::fmt::Debug {
     fn synthetic_id(&self, ctx: &Ctx) -> Option<SyntheticTokenId>;
 }
 
-trait TokenConvertor: Sized {
+trait TokenConverter: Sized {
     type Token: SrcToken<Self>;
 
     fn convert_doc_comment(&self, token: &Self::Token) -> Option<Vec<tt::TokenTree>>;
@@ -454,25 +486,25 @@ trait TokenConvertor: Sized {
     fn id_alloc(&mut self) -> &mut TokenIdAlloc;
 }
 
-impl<'a> SrcToken<RawConvertor<'a>> for usize {
-    fn kind(&self, ctx: &RawConvertor<'a>) -> SyntaxKind {
+impl<'a> SrcToken<RawConverter<'a>> for usize {
+    fn kind(&self, ctx: &RawConverter<'a>) -> SyntaxKind {
         ctx.lexed.kind(*self)
     }
 
-    fn to_char(&self, ctx: &RawConvertor<'a>) -> Option<char> {
+    fn to_char(&self, ctx: &RawConverter<'a>) -> Option<char> {
         ctx.lexed.text(*self).chars().next()
     }
 
-    fn to_text(&self, ctx: &RawConvertor<'_>) -> SmolStr {
+    fn to_text(&self, ctx: &RawConverter<'_>) -> SmolStr {
         ctx.lexed.text(*self).into()
     }
 
-    fn synthetic_id(&self, _ctx: &RawConvertor<'a>) -> Option<SyntheticTokenId> {
+    fn synthetic_id(&self, _ctx: &RawConverter<'a>) -> Option<SyntheticTokenId> {
         None
     }
 }
 
-impl<'a> TokenConvertor for RawConvertor<'a> {
+impl<'a> TokenConverter for RawConverter<'a> {
     type Token = usize;
 
     fn convert_doc_comment(&self, &token: &usize) -> Option<Vec<tt::TokenTree>> {
@@ -504,7 +536,7 @@ impl<'a> TokenConvertor for RawConvertor<'a> {
     }
 }
 
-struct Convertor {
+struct Converter {
     id_alloc: TokenIdAlloc,
     current: Option<SyntaxToken>,
     current_synthetic: Vec<SyntheticToken>,
@@ -515,7 +547,7 @@ struct Convertor {
     punct_offset: Option<(SyntaxToken, TextSize)>,
 }
 
-impl Convertor {
+impl Converter {
     fn new(
         node: &SyntaxNode,
         global_offset: TextSize,
@@ -523,11 +555,11 @@ impl Convertor {
         next_id: u32,
         mut replace: FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
         mut append: FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
-    ) -> Convertor {
+    ) -> Converter {
         let range = node.text_range();
         let mut preorder = node.preorder_with_tokens();
         let (first, synthetic) = Self::next_token(&mut preorder, &mut replace, &mut append);
-        Convertor {
+        Converter {
             id_alloc: { TokenIdAlloc { map: existing_token_map, global_offset, next_id } },
             current: first,
             current_synthetic: synthetic,
@@ -590,15 +622,15 @@ impl SynToken {
     }
 }
 
-impl SrcToken<Convertor> for SynToken {
-    fn kind(&self, _ctx: &Convertor) -> SyntaxKind {
+impl SrcToken<Converter> for SynToken {
+    fn kind(&self, ctx: &Converter) -> SyntaxKind {
         match self {
             SynToken::Ordinary(token) => token.kind(),
-            SynToken::Punch(token, _) => token.kind(),
+            SynToken::Punch(..) => SyntaxKind::from_char(self.to_char(ctx).unwrap()).unwrap(),
             SynToken::Synthetic(token) => token.kind,
         }
     }
-    fn to_char(&self, _ctx: &Convertor) -> Option<char> {
+    fn to_char(&self, _ctx: &Converter) -> Option<char> {
         match self {
             SynToken::Ordinary(_) => None,
             SynToken::Punch(it, i) => it.text().chars().nth((*i).into()),
@@ -606,7 +638,7 @@ impl SrcToken<Convertor> for SynToken {
             SynToken::Synthetic(_) => None,
         }
     }
-    fn to_text(&self, _ctx: &Convertor) -> SmolStr {
+    fn to_text(&self, _ctx: &Converter) -> SmolStr {
         match self {
             SynToken::Ordinary(token) => token.text().into(),
             SynToken::Punch(token, _) => token.text().into(),
@@ -614,7 +646,7 @@ impl SrcToken<Convertor> for SynToken {
         }
     }
 
-    fn synthetic_id(&self, _ctx: &Convertor) -> Option<SyntheticTokenId> {
+    fn synthetic_id(&self, _ctx: &Converter) -> Option<SyntheticTokenId> {
         match self {
             SynToken::Synthetic(token) => Some(token.id),
             _ => None,
@@ -622,7 +654,7 @@ impl SrcToken<Convertor> for SynToken {
     }
 }
 
-impl TokenConvertor for Convertor {
+impl TokenConverter for Converter {
     type Token = SynToken;
     fn convert_doc_comment(&self, token: &Self::Token) -> Option<Vec<tt::TokenTree>> {
         convert_doc_comment(token.token()?)
@@ -651,7 +683,7 @@ impl TokenConvertor for Convertor {
         }
 
         let curr = self.current.clone()?;
-        if !&self.range.contains_range(curr.text_range()) {
+        if !self.range.contains_range(curr.text_range()) {
             return None;
         }
         let (new_current, new_synth) =
@@ -809,12 +841,15 @@ impl<'a> TtTreeSink<'a> {
         let next = last.bump();
         if let (
             Some(tt::buffer::TokenTreeRef::Leaf(tt::Leaf::Punct(curr), _)),
-            Some(tt::buffer::TokenTreeRef::Leaf(tt::Leaf::Punct(_), _)),
+            Some(tt::buffer::TokenTreeRef::Leaf(tt::Leaf::Punct(next), _)),
         ) = (last.token_tree(), next.token_tree())
         {
             // Note: We always assume the semi-colon would be the last token in
             // other parts of RA such that we don't add whitespace here.
-            if curr.spacing == tt::Spacing::Alone && curr.char != ';' {
+            //
+            // When `next` is a `Punct` of `'`, that's a part of a lifetime identifier so we don't
+            // need to add whitespace either.
+            if curr.spacing == tt::Spacing::Alone && curr.char != ';' && next.char != '\'' {
                 self.inner.token(WHITESPACE, " ");
                 self.text_pos += TextSize::of(' ');
             }
diff --git a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge/tests.rs b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge/tests.rs
new file mode 100644
index 00000000000..4e04d2bc1c7
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge/tests.rs
@@ -0,0 +1,93 @@
+use std::collections::HashMap;
+
+use syntax::{ast, AstNode};
+use test_utils::extract_annotations;
+use tt::{
+    buffer::{TokenBuffer, TokenTreeRef},
+    Leaf, Punct, Spacing,
+};
+
+use super::syntax_node_to_token_tree;
+
+fn check_punct_spacing(fixture: &str) {
+    let source_file = ast::SourceFile::parse(fixture).ok().unwrap();
+    let (subtree, token_map) = syntax_node_to_token_tree(source_file.syntax());
+    let mut annotations: HashMap<_, _> = extract_annotations(fixture)
+        .into_iter()
+        .map(|(range, annotation)| {
+            let token = token_map.token_by_range(range).expect("no token found");
+            let spacing = match annotation.as_str() {
+                "Alone" => Spacing::Alone,
+                "Joint" => Spacing::Joint,
+                a => panic!("unknown annotation: {}", a),
+            };
+            (token, spacing)
+        })
+        .collect();
+
+    let buf = TokenBuffer::from_subtree(&subtree);
+    let mut cursor = buf.begin();
+    while !cursor.eof() {
+        while let Some(token_tree) = cursor.token_tree() {
+            if let TokenTreeRef::Leaf(Leaf::Punct(Punct { spacing, id, .. }), _) = token_tree {
+                if let Some(expected) = annotations.remove(&id) {
+                    assert_eq!(expected, *spacing);
+                }
+            }
+            cursor = cursor.bump_subtree();
+        }
+        cursor = cursor.bump();
+    }
+
+    assert!(annotations.is_empty(), "unchecked annotations: {:?}", annotations);
+}
+
+#[test]
+fn punct_spacing() {
+    check_punct_spacing(
+        r#"
+fn main() {
+    0+0;
+   //^ Alone
+    0+(0);
+   //^ Alone
+    0<=0;
+   //^ Joint
+   // ^ Alone
+    0<=(0);
+   // ^ Alone
+    a=0;
+   //^ Alone
+    a=(0);
+   //^ Alone
+    a+=0;
+   //^ Joint
+   // ^ Alone
+    a+=(0);
+   // ^ Alone
+    a&&b;
+   //^ Joint
+   // ^ Alone
+    a&&(b);
+   // ^ Alone
+    foo::bar;
+   //  ^ Joint
+   //   ^ Alone
+    use foo::{bar,baz,};
+   //       ^ Alone
+   //            ^ Alone
+   //                ^ Alone
+    struct Struct<'a> {};
+   //            ^ Joint
+   //             ^ Joint
+    Struct::<0>;
+   //       ^ Alone
+    Struct::<{0}>;
+   //       ^ Alone
+    ;;
+  //^ Joint
+  // ^ Alone
+}
+        "#,
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/parser/Cargo.toml b/src/tools/rust-analyzer/crates/parser/Cargo.toml
index a286a6bcddd..d1420de8937 100644
--- a/src/tools/rust-analyzer/crates/parser/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/parser/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/paths/Cargo.toml b/src/tools/rust-analyzer/crates/paths/Cargo.toml
index 5e83de7d994..d23a63d2a97 100644
--- a/src/tools/rust-analyzer/crates/paths/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/paths/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
index 54879c1870c..f261f3def45 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml
index 9d0da5dee9c..7991e125ab8 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [dependencies]
 proc-macro-srv = { version = "0.0.0", path = "../proc-macro-srv" }
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
index e39026ac70b..a136abc12b7 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/mod.rs
index 2f854bc1595..0ce099ae0ba 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/mod.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/mod.rs
@@ -117,7 +117,7 @@ impl Abi {
                 let inner = unsafe { Abi_1_63::from_lib(lib, symbol_name) }?;
                 Ok(Abi::Abi1_63(inner))
             }
-            _ => Err(LoadProcMacroDylibError::UnsupportedABI),
+            _ => Err(LoadProcMacroDylibError::UnsupportedABI(info.version_string.clone())),
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs
index 7aba74e5396..0722cd89d72 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs
@@ -80,14 +80,14 @@ fn load_library(file: &Path) -> Result<Library, libloading::Error> {
 pub enum LoadProcMacroDylibError {
     Io(io::Error),
     LibLoading(libloading::Error),
-    UnsupportedABI,
+    UnsupportedABI(String),
 }
 
 impl fmt::Display for LoadProcMacroDylibError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             Self::Io(e) => e.fmt(f),
-            Self::UnsupportedABI => write!(f, "unsupported ABI version"),
+            Self::UnsupportedABI(v) => write!(f, "unsupported ABI `{v}`"),
             Self::LibLoading(e) => e.fmt(f),
         }
     }
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs
index 72a2dfe72d3..b4f5ebd157f 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs
@@ -113,12 +113,12 @@ impl ProcMacroSrv {
 
     fn expander(&mut self, path: &Path) -> Result<&dylib::Expander, String> {
         let time = fs::metadata(path).and_then(|it| it.modified()).map_err(|err| {
-            format!("Failed to get file metadata for {}: {:?}", path.display(), err)
+            format!("Failed to get file metadata for {}: {}", path.display(), err)
         })?;
 
         Ok(match self.expanders.entry((path.to_path_buf(), time)) {
             Entry::Vacant(v) => v.insert(dylib::Expander::new(path).map_err(|err| {
-                format!("Cannot create expander for {}: {:?}", path.display(), err)
+                format!("Cannot create expander for {}: {}", path.display(), err)
             })?),
             Entry::Occupied(e) => e.into_mut(),
         })
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
index b46cdddcf6b..cc0fc91fe98 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
@@ -19,7 +19,7 @@ fn test_derive_error() {
         expect![[r##"
             SUBTREE $
               IDENT   compile_error 4294967295
-              PUNCH   ! [joint] 4294967295
+              PUNCH   ! [alone] 4294967295
               SUBTREE () 4294967295
                 LITERAL "#[derive(DeriveError)] struct S ;" 4294967295
               PUNCH   ; [alone] 4294967295"##]],
@@ -109,7 +109,7 @@ fn test_fn_like_macro_clone_literals() {
               PUNCH   , [alone] 4294967295
               LITERAL 2_u32 4294967295
               PUNCH   , [alone] 4294967295
-              PUNCH   - [joint] 4294967295
+              PUNCH   - [alone] 4294967295
               LITERAL 4i64 4294967295
               PUNCH   , [alone] 4294967295
               LITERAL 3.14f32 4294967295
@@ -130,7 +130,7 @@ fn test_attr_macro() {
         expect![[r##"
             SUBTREE $
               IDENT   compile_error 4294967295
-              PUNCH   ! [joint] 4294967295
+              PUNCH   ! [alone] 4294967295
               SUBTREE () 4294967295
                 LITERAL "#[attr_error(some arguments)] mod m {}" 4294967295
               PUNCH   ; [alone] 4294967295"##]],
diff --git a/src/tools/rust-analyzer/crates/proc-macro-test/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-test/Cargo.toml
index 684477191b2..d2a79f91074 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-test/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-test/Cargo.toml
@@ -3,7 +3,7 @@ name = "proc-macro-test"
 version = "0.0.0"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 publish = false
 
 [lib]
diff --git a/src/tools/rust-analyzer/crates/proc-macro-test/imp/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-test/imp/Cargo.toml
index 2d1fc3c5c7a..1bd14070e90 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-test/imp/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-test/imp/Cargo.toml
@@ -3,7 +3,7 @@ name = "proc-macro-test-impl"
 version = "0.0.0"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 publish = false
 
 [lib]
diff --git a/src/tools/rust-analyzer/crates/profile/Cargo.toml b/src/tools/rust-analyzer/crates/profile/Cargo.toml
index 5697aea964f..01d1735bf78 100644
--- a/src/tools/rust-analyzer/crates/profile/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/profile/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/project-model/Cargo.toml b/src/tools/rust-analyzer/crates/project-model/Cargo.toml
index cf9868740cb..39902a53214 100644
--- a/src/tools/rust-analyzer/crates/project-model/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/project-model/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
index a26a7c57acf..ae2b41f27d5 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
@@ -69,7 +69,7 @@ impl WorkspaceBuildScripts {
                 cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]);
 
                 // --all-targets includes tests, benches and examples in addition to the
-                // default lib and bins. This is an independent concept from the --targets
+                // default lib and bins. This is an independent concept from the --target
                 // flag below.
                 cmd.arg("--all-targets");
 
diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
index b4c2ba43677..02ec7a4f6f9 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
@@ -270,11 +270,7 @@ impl CargoWorkspace {
         config: &CargoConfig,
         progress: &dyn Fn(String),
     ) -> Result<cargo_metadata::Metadata> {
-        let target = config
-            .target
-            .clone()
-            .or_else(|| cargo_config_build_target(cargo_toml, &config.extra_env))
-            .or_else(|| rustc_discover_host_triple(cargo_toml, &config.extra_env));
+        let targets = find_list_of_build_targets(config, cargo_toml);
 
         let mut meta = MetadataCommand::new();
         meta.cargo_path(toolchain::cargo());
@@ -294,8 +290,12 @@ impl CargoWorkspace {
         }
         meta.current_dir(current_dir.as_os_str());
 
-        if let Some(target) = target {
-            meta.other_options(vec![String::from("--filter-platform"), target]);
+        if !targets.is_empty() {
+            let other_options: Vec<_> = targets
+                .into_iter()
+                .flat_map(|target| ["--filter-platform".to_string(), target])
+                .collect();
+            meta.other_options(other_options);
         }
 
         // FIXME: Fetching metadata is a slow process, as it might require
@@ -469,6 +469,19 @@ impl CargoWorkspace {
     }
 }
 
+fn find_list_of_build_targets(config: &CargoConfig, cargo_toml: &ManifestPath) -> Vec<String> {
+    if let Some(target) = &config.target {
+        return [target.into()].to_vec();
+    }
+
+    let build_targets = cargo_config_build_target(cargo_toml, &config.extra_env);
+    if !build_targets.is_empty() {
+        return build_targets;
+    }
+
+    rustc_discover_host_triple(cargo_toml, &config.extra_env).into_iter().collect()
+}
+
 fn rustc_discover_host_triple(
     cargo_toml: &ManifestPath,
     extra_env: &FxHashMap<String, String>,
@@ -499,7 +512,7 @@ fn rustc_discover_host_triple(
 fn cargo_config_build_target(
     cargo_toml: &ManifestPath,
     extra_env: &FxHashMap<String, String>,
-) -> Option<String> {
+) -> Vec<String> {
     let mut cargo_config = Command::new(toolchain::cargo());
     cargo_config.envs(extra_env);
     cargo_config
@@ -507,12 +520,21 @@ fn cargo_config_build_target(
         .args(&["-Z", "unstable-options", "config", "get", "build.target"])
         .env("RUSTC_BOOTSTRAP", "1");
     // if successful we receive `build.target = "target-triple"`
+    // or `build.target = ["<target 1>", ..]`
     tracing::debug!("Discovering cargo config target by {:?}", cargo_config);
-    match utf8_stdout(cargo_config) {
-        Ok(stdout) => stdout
-            .strip_prefix("build.target = \"")
-            .and_then(|stdout| stdout.strip_suffix('"'))
-            .map(ToOwned::to_owned),
-        Err(_) => None,
+    utf8_stdout(cargo_config).map(parse_output_cargo_config_build_target).unwrap_or_default()
+}
+
+fn parse_output_cargo_config_build_target(stdout: String) -> Vec<String> {
+    let trimmed = stdout.trim_start_matches("build.target = ").trim_matches('"');
+
+    if !trimmed.starts_with('[') {
+        return [trimmed.to_string()].to_vec();
+    }
+
+    let res = serde_json::from_str(trimmed);
+    if let Err(e) = &res {
+        tracing::warn!("Failed to parse `build.target` as an array of target: {}`", e);
     }
+    res.unwrap_or_default()
 }
diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
index fa8d76f3f45..f6c09a27c9d 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
@@ -128,14 +128,18 @@ impl Sysroot {
         }
 
         if let Some(alloc) = sysroot.by_name("alloc") {
-            if let Some(core) = sysroot.by_name("core") {
-                sysroot.crates[alloc].deps.push(core);
+            for dep in ALLOC_DEPS.trim().lines() {
+                if let Some(dep) = sysroot.by_name(dep) {
+                    sysroot.crates[alloc].deps.push(dep)
+                }
             }
         }
 
         if let Some(proc_macro) = sysroot.by_name("proc_macro") {
-            if let Some(std) = sysroot.by_name("std") {
-                sysroot.crates[proc_macro].deps.push(std);
+            for dep in PROC_MACRO_DEPS.trim().lines() {
+                if let Some(dep) = sysroot.by_name(dep) {
+                    sysroot.crates[proc_macro].deps.push(dep)
+                }
             }
         }
 
@@ -239,6 +243,7 @@ fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
 
 const SYSROOT_CRATES: &str = "
 alloc
+backtrace
 core
 panic_abort
 panic_unwind
@@ -246,17 +251,19 @@ proc_macro
 profiler_builtins
 std
 stdarch/crates/std_detect
-term
 test
 unwind";
 
+const ALLOC_DEPS: &str = "core";
+
 const STD_DEPS: &str = "
 alloc
-core
-panic_abort
 panic_unwind
+panic_abort
+core
 profiler_builtins
+unwind
 std_detect
-term
-test
-unwind";
+test";
+
+const PROC_MACRO_DEPS: &str = "std";
diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
index e2444e24974..a1cb438bddc 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
@@ -1566,10 +1566,10 @@ fn rust_project_hello_world_project_model() {
                             },
                             Dependency {
                                 crate_id: CrateId(
-                                    1,
+                                    3,
                                 ),
                                 name: CrateName(
-                                    "core",
+                                    "panic_unwind",
                                 ),
                                 prelude: true,
                             },
@@ -1584,10 +1584,10 @@ fn rust_project_hello_world_project_model() {
                             },
                             Dependency {
                                 crate_id: CrateId(
-                                    3,
+                                    1,
                                 ),
                                 name: CrateName(
-                                    "panic_unwind",
+                                    "core",
                                 ),
                                 prelude: true,
                             },
@@ -1602,40 +1602,31 @@ fn rust_project_hello_world_project_model() {
                             },
                             Dependency {
                                 crate_id: CrateId(
-                                    7,
+                                    9,
                                 ),
                                 name: CrateName(
-                                    "std_detect",
+                                    "unwind",
                                 ),
                                 prelude: true,
                             },
                             Dependency {
                                 crate_id: CrateId(
-                                    8,
+                                    7,
                                 ),
                                 name: CrateName(
-                                    "term",
+                                    "std_detect",
                                 ),
                                 prelude: true,
                             },
                             Dependency {
                                 crate_id: CrateId(
-                                    9,
+                                    8,
                                 ),
                                 name: CrateName(
                                     "test",
                                 ),
                                 prelude: true,
                             },
-                            Dependency {
-                                crate_id: CrateId(
-                                    10,
-                                ),
-                                name: CrateName(
-                                    "unwind",
-                                ),
-                                prelude: true,
-                            },
                         ],
                         proc_macro: Err(
                             "no proc macro loaded for sysroot crate",
@@ -1690,40 +1681,6 @@ fn rust_project_hello_world_project_model() {
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "term",
-                                ),
-                                canonical_name: "term",
-                            },
-                        ),
-                        cfg_options: CfgOptions(
-                            [],
-                        ),
-                        potential_cfg_options: CfgOptions(
-                            [],
-                        ),
-                        env: Env {
-                            entries: {},
-                        },
-                        dependencies: [],
-                        proc_macro: Err(
-                            "no proc macro loaded for sysroot crate",
-                        ),
-                        origin: Lang(
-                            Other,
-                        ),
-                        is_proc_macro: false,
-                    },
-                    CrateId(
-                        9,
-                    ): CrateData {
-                        root_file_id: FileId(
-                            10,
-                        ),
-                        edition: Edition2018,
-                        version: None,
-                        display_name: Some(
-                            CrateDisplayName {
-                                crate_name: CrateName(
                                     "test",
                                 ),
                                 canonical_name: "test",
@@ -1748,10 +1705,10 @@ fn rust_project_hello_world_project_model() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        10,
+                        9,
                     ): CrateData {
                         root_file_id: FileId(
-                            11,
+                            10,
                         ),
                         edition: Edition2018,
                         version: None,
@@ -1782,10 +1739,10 @@ fn rust_project_hello_world_project_model() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        11,
+                        10,
                     ): CrateData {
                         root_file_id: FileId(
-                            12,
+                            11,
                         ),
                         edition: Edition2018,
                         version: None,
@@ -1836,7 +1793,7 @@ fn rust_project_hello_world_project_model() {
                             },
                             Dependency {
                                 crate_id: CrateId(
-                                    9,
+                                    8,
                                 ),
                                 name: CrateName(
                                     "test",
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index 2780c62ed11..3d199ed24af 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -377,6 +377,21 @@ impl ProjectWorkspace {
         }
     }
 
+    pub fn find_sysroot_proc_macro_srv(&self) -> Option<AbsPathBuf> {
+        match self {
+            ProjectWorkspace::Cargo { sysroot: Some(sysroot), .. }
+            | ProjectWorkspace::Json { sysroot: Some(sysroot), .. } => {
+                let standalone_server_name =
+                    format!("rust-analyzer-proc-macro-srv{}", std::env::consts::EXE_SUFFIX);
+                ["libexec", "lib"]
+                    .into_iter()
+                    .map(|segment| sysroot.root().join(segment).join(&standalone_server_name))
+                    .find(|server_path| std::fs::metadata(&server_path).is_ok())
+            }
+            _ => None,
+        }
+    }
+
     /// Returns the roots for the current `ProjectWorkspace`
     /// The return type contains the path and whether or not
     /// the root is a member of the current workspace
@@ -509,14 +524,14 @@ impl ProjectWorkspace {
                 build_scripts,
                 toolchain: _,
             } => cargo_to_crate_graph(
-                rustc_cfg.clone(),
-                cfg_overrides,
                 load_proc_macro,
                 load,
+                rustc,
                 cargo,
-                build_scripts,
                 sysroot.as_ref(),
-                rustc,
+                rustc_cfg.clone(),
+                cfg_overrides,
+                build_scripts,
             ),
             ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => {
                 detached_files_to_crate_graph(rustc_cfg.clone(), load, files, sysroot)
@@ -602,7 +617,7 @@ fn project_json_to_crate_graph(
     for (from, krate) in project.crates() {
         if let Some(&from) = crates.get(&from) {
             if let Some((public_deps, libproc_macro)) = &sysroot_deps {
-                public_deps.add(from, &mut crate_graph);
+                public_deps.add_to_crate_graph(&mut crate_graph, from);
                 if krate.is_proc_macro {
                     if let Some(proc_macro) = libproc_macro {
                         add_dep(
@@ -626,14 +641,14 @@ fn project_json_to_crate_graph(
 }
 
 fn cargo_to_crate_graph(
-    rustc_cfg: Vec<CfgFlag>,
-    override_cfg: &CfgOverrides,
     load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> ProcMacroLoadResult,
     load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
+    rustc: &Option<CargoWorkspace>,
     cargo: &CargoWorkspace,
-    build_scripts: &WorkspaceBuildScripts,
     sysroot: Option<&Sysroot>,
-    rustc: &Option<CargoWorkspace>,
+    rustc_cfg: Vec<CfgFlag>,
+    override_cfg: &CfgOverrides,
+    build_scripts: &WorkspaceBuildScripts,
 ) -> CrateGraph {
     let _p = profile::span("cargo_to_crate_graph");
     let mut crate_graph = CrateGraph::default();
@@ -642,13 +657,15 @@ fn cargo_to_crate_graph(
         None => (SysrootPublicDeps::default(), None),
     };
 
-    let mut cfg_options = CfgOptions::default();
-    cfg_options.extend(rustc_cfg);
+    let cfg_options = {
+        let mut cfg_options = CfgOptions::default();
+        cfg_options.extend(rustc_cfg);
+        cfg_options.insert_atom("debug_assertions".into());
+        cfg_options
+    };
 
     let mut pkg_to_lib_crate = FxHashMap::default();
 
-    cfg_options.insert_atom("debug_assertions".into());
-
     let mut pkg_crates = FxHashMap::default();
     // Does any crate signal to rust-analyzer that they need the rustc_private crates?
     let mut has_private = false;
@@ -723,7 +740,7 @@ fn cargo_to_crate_graph(
         // Set deps to the core, std and to the lib target of the current package
         for &(from, kind) in pkg_crates.get(&pkg).into_iter().flatten() {
             // Add sysroot deps first so that a lib target named `core` etc. can overwrite them.
-            public_deps.add(from, &mut crate_graph);
+            public_deps.add_to_crate_graph(&mut crate_graph, from);
 
             if let Some((to, name)) = lib_tgt.clone() {
                 if to != from && kind != TargetKind::BuildScript {
@@ -767,15 +784,16 @@ fn cargo_to_crate_graph(
         if let Some(rustc_workspace) = rustc {
             handle_rustc_crates(
                 &mut crate_graph,
-                rustc_workspace,
+                &mut pkg_to_lib_crate,
                 load,
-                &cfg_options,
-                override_cfg,
                 load_proc_macro,
-                &mut pkg_to_lib_crate,
-                &public_deps,
+                rustc_workspace,
                 cargo,
+                &public_deps,
+                libproc_macro,
                 &pkg_crates,
+                &cfg_options,
+                override_cfg,
                 build_scripts,
             );
         }
@@ -825,28 +843,29 @@ fn detached_files_to_crate_graph(
             },
         );
 
-        public_deps.add(detached_file_crate, &mut crate_graph);
+        public_deps.add_to_crate_graph(&mut crate_graph, detached_file_crate);
     }
     crate_graph
 }
 
 fn handle_rustc_crates(
     crate_graph: &mut CrateGraph,
-    rustc_workspace: &CargoWorkspace,
+    pkg_to_lib_crate: &mut FxHashMap<Package, CrateId>,
     load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
-    cfg_options: &CfgOptions,
-    override_cfg: &CfgOverrides,
     load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> ProcMacroLoadResult,
-    pkg_to_lib_crate: &mut FxHashMap<Package, CrateId>,
-    public_deps: &SysrootPublicDeps,
+    rustc_workspace: &CargoWorkspace,
     cargo: &CargoWorkspace,
+    public_deps: &SysrootPublicDeps,
+    libproc_macro: Option<CrateId>,
     pkg_crates: &FxHashMap<Package, Vec<(CrateId, TargetKind)>>,
+    cfg_options: &CfgOptions,
+    override_cfg: &CfgOverrides,
     build_scripts: &WorkspaceBuildScripts,
 ) {
     let mut rustc_pkg_crates = FxHashMap::default();
     // The root package of the rustc-dev component is rustc_driver, so we match that
     let root_pkg =
-        rustc_workspace.packages().find(|package| rustc_workspace[*package].name == "rustc_driver");
+        rustc_workspace.packages().find(|&package| rustc_workspace[package].name == "rustc_driver");
     // The rustc workspace might be incomplete (such as if rustc-dev is not
     // installed for the current toolchain) and `rustc_source` is set to discover.
     if let Some(root_pkg) = root_pkg {
@@ -901,7 +920,16 @@ fn handle_rustc_crates(
                     );
                     pkg_to_lib_crate.insert(pkg, crate_id);
                     // Add dependencies on core / std / alloc for this crate
-                    public_deps.add(crate_id, crate_graph);
+                    public_deps.add_to_crate_graph(crate_graph, crate_id);
+                    if let Some(proc_macro) = libproc_macro {
+                        add_dep_with_prelude(
+                            crate_graph,
+                            crate_id,
+                            CrateName::new("proc_macro").unwrap(),
+                            proc_macro,
+                            rustc_workspace[tgt].is_proc_macro,
+                        );
+                    }
                     rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
                 }
             }
@@ -1009,7 +1037,7 @@ struct SysrootPublicDeps {
 
 impl SysrootPublicDeps {
     /// Makes `from` depend on the public sysroot crates.
-    fn add(&self, from: CrateId, crate_graph: &mut CrateGraph) {
+    fn add_to_crate_graph(&self, crate_graph: &mut CrateGraph, from: CrateId) {
         for (name, krate, prelude) in &self.deps {
             add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude);
         }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
index 7ae5324ab05..56f14fe1874 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
@@ -8,7 +8,7 @@ documentation = "https://rust-analyzer.github.io/manual.html"
 license = "MIT OR Apache-2.0"
 autobins = false
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cargo_target_spec.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cargo_target_spec.rs
index 6ede194babc..cf51cf15a0e 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cargo_target_spec.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cargo_target_spec.rs
@@ -3,11 +3,11 @@
 use std::mem;
 
 use cfg::{CfgAtom, CfgExpr};
-use ide::{FileId, RunnableKind, TestId};
+use ide::{Cancellable, FileId, RunnableKind, TestId};
 use project_model::{self, CargoFeatures, ManifestPath, TargetKind};
 use vfs::AbsPathBuf;
 
-use crate::{global_state::GlobalStateSnapshot, Result};
+use crate::global_state::GlobalStateSnapshot;
 
 /// Abstract representation of Cargo target.
 ///
@@ -29,7 +29,7 @@ impl CargoTargetSpec {
         spec: Option<CargoTargetSpec>,
         kind: &RunnableKind,
         cfg: &Option<CfgExpr>,
-    ) -> Result<(Vec<String>, Vec<String>)> {
+    ) -> (Vec<String>, Vec<String>) {
         let mut args = Vec::new();
         let mut extra_args = Vec::new();
 
@@ -111,13 +111,13 @@ impl CargoTargetSpec {
                 }
             }
         }
-        Ok((args, extra_args))
+        (args, extra_args)
     }
 
     pub(crate) fn for_file(
         global_state_snapshot: &GlobalStateSnapshot,
         file_id: FileId,
-    ) -> Result<Option<CargoTargetSpec>> {
+    ) -> Cancellable<Option<CargoTargetSpec>> {
         let crate_id = match &*global_state_snapshot.analysis.crates_for(file_id)? {
             &[crate_id, ..] => crate_id,
             _ => return Ok(None),
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/load_cargo.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/load_cargo.rs
index 5dba545b871..762d7d3a18e 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -60,24 +60,12 @@ pub fn load_workspace(
     };
 
     let proc_macro_client = if load_config.with_proc_macro {
-        let mut path = AbsPathBuf::assert(std::env::current_exe()?);
-        let mut args = vec!["proc-macro"];
-
-        if let ProjectWorkspace::Cargo { sysroot, .. } | ProjectWorkspace::Json { sysroot, .. } =
-            &ws
-        {
-            if let Some(sysroot) = sysroot.as_ref() {
-                let standalone_server_name =
-                    format!("rust-analyzer-proc-macro-srv{}", std::env::consts::EXE_SUFFIX);
-                let server_path = sysroot.root().join("libexec").join(&standalone_server_name);
-                if std::fs::metadata(&server_path).is_ok() {
-                    path = server_path;
-                    args = vec![];
-                }
-            }
-        }
+        let (server_path, args): (_, &[_]) = match ws.find_sysroot_proc_macro_srv() {
+            Some(server_path) => (server_path, &[]),
+            None => (AbsPathBuf::assert(std::env::current_exe()?), &["proc-macro"]),
+        };
 
-        ProcMacroServer::spawn(path.clone(), args.clone()).map_err(|e| e.to_string())
+        ProcMacroServer::spawn(server_path, args).map_err(|e| e.to_string())
     } else {
         Err("proc macro server disabled".to_owned())
     };
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
index ca7ba896b67..9edd045ab07 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
@@ -47,30 +47,27 @@ impl flags::Scip {
 
         let si = StaticIndex::compute(&analysis);
 
-        let mut index = scip_types::Index {
-            metadata: Some(scip_types::Metadata {
-                version: scip_types::ProtocolVersion::UnspecifiedProtocolVersion.into(),
-                tool_info: Some(scip_types::ToolInfo {
-                    name: "rust-analyzer".to_owned(),
-                    version: "0.1".to_owned(),
-                    arguments: vec![],
-                    ..Default::default()
-                })
-                .into(),
-                project_root: format!(
-                    "file://{}",
-                    path.normalize()
-                        .as_os_str()
-                        .to_str()
-                        .ok_or(anyhow::anyhow!("Unable to normalize project_root path"))?
-                        .to_string()
-                ),
-                text_document_encoding: scip_types::TextEncoding::UTF8.into(),
-                ..Default::default()
+        let metadata = scip_types::Metadata {
+            version: scip_types::ProtocolVersion::UnspecifiedProtocolVersion.into(),
+            tool_info: Some(scip_types::ToolInfo {
+                name: "rust-analyzer".to_owned(),
+                version: "0.1".to_owned(),
+                arguments: vec![],
+                special_fields: Default::default(),
             })
             .into(),
-            ..Default::default()
+            project_root: format!(
+                "file://{}",
+                path.normalize()
+                    .as_os_str()
+                    .to_str()
+                    .ok_or(anyhow::anyhow!("Unable to normalize project_root path"))?
+                    .to_string()
+            ),
+            text_document_encoding: scip_types::TextEncoding::UTF8.into(),
+            special_fields: Default::default(),
         };
+        let mut documents = Vec::new();
 
         let mut symbols_emitted: HashSet<TokenId> = HashSet::default();
         let mut tokens_to_symbol: HashMap<TokenId, String> = HashMap::new();
@@ -95,18 +92,14 @@ impl flags::Scip {
                 endings: LineEndings::Unix,
             };
 
-            let mut doc = scip_types::Document {
-                relative_path,
-                language: "rust".to_string(),
-                ..Default::default()
-            };
+            let mut occurrences = Vec::new();
+            let mut symbols = Vec::new();
 
-            tokens.into_iter().for_each(|(range, id)| {
+            tokens.into_iter().for_each(|(text_range, id)| {
                 let token = si.tokens.get(id).unwrap();
 
-                let mut occurrence = scip_types::Occurrence::default();
-                occurrence.range = text_range_to_scip_range(&line_index, range);
-                occurrence.symbol = tokens_to_symbol
+                let range = text_range_to_scip_range(&line_index, text_range);
+                let symbol = tokens_to_symbol
                     .entry(id)
                     .or_insert_with(|| {
                         let symbol = token_to_symbol(&token).unwrap_or_else(&mut new_local_symbol);
@@ -114,34 +107,62 @@ impl flags::Scip {
                     })
                     .clone();
 
+                let mut symbol_roles = Default::default();
+
                 if let Some(def) = token.definition {
-                    if def.range == range {
-                        occurrence.symbol_roles |= scip_types::SymbolRole::Definition as i32;
+                    if def.range == text_range {
+                        symbol_roles |= scip_types::SymbolRole::Definition as i32;
                     }
 
                     if symbols_emitted.insert(id) {
-                        let mut symbol_info = scip_types::SymbolInformation::default();
-                        symbol_info.symbol = occurrence.symbol.clone();
-                        if let Some(hover) = &token.hover {
-                            if !hover.markup.as_str().is_empty() {
-                                symbol_info.documentation = vec![hover.markup.as_str().to_string()];
-                            }
-                        }
-
-                        doc.symbols.push(symbol_info)
+                        let documentation = token
+                            .hover
+                            .as_ref()
+                            .map(|hover| hover.markup.as_str())
+                            .filter(|it| !it.is_empty())
+                            .map(|it| vec![it.to_owned()]);
+                        let symbol_info = scip_types::SymbolInformation {
+                            symbol: symbol.clone(),
+                            documentation: documentation.unwrap_or_default(),
+                            relationships: Vec::new(),
+                            special_fields: Default::default(),
+                        };
+
+                        symbols.push(symbol_info)
                     }
                 }
 
-                doc.occurrences.push(occurrence);
+                occurrences.push(scip_types::Occurrence {
+                    range,
+                    symbol,
+                    symbol_roles,
+                    override_documentation: Vec::new(),
+                    syntax_kind: Default::default(),
+                    diagnostics: Vec::new(),
+                    special_fields: Default::default(),
+                });
             });
 
-            if doc.occurrences.is_empty() {
+            if occurrences.is_empty() {
                 continue;
             }
 
-            index.documents.push(doc);
+            documents.push(scip_types::Document {
+                relative_path,
+                language: "rust".to_string(),
+                occurrences,
+                symbols,
+                special_fields: Default::default(),
+            });
         }
 
+        let index = scip_types::Index {
+            metadata: Some(metadata).into(),
+            documents,
+            external_symbols: Vec::new(),
+            special_fields: Default::default(),
+        };
+
         scip::write_message_to_file("index.scip", index)
             .map_err(|err| anyhow::anyhow!("Failed to write scip to file: {}", err))?;
 
@@ -181,7 +202,7 @@ fn new_descriptor_str(
         name: name.to_string(),
         disambiguator: "".to_string(),
         suffix: suffix.into(),
-        ..Default::default()
+        special_fields: Default::default(),
     }
 }
 
@@ -232,11 +253,11 @@ fn token_to_symbol(token: &TokenStaticData) -> Option<scip_types::Symbol> {
             manager: "cargo".to_string(),
             name: package_name,
             version: version.unwrap_or_else(|| ".".to_string()),
-            ..Default::default()
+            special_fields: Default::default(),
         })
         .into(),
         descriptors,
-        ..Default::default()
+        special_fields: Default::default(),
     })
 }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index c278ba2d7c5..6b2f22faa71 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -118,9 +118,11 @@ config_data! {
         /// This option does not take effect until rust-analyzer is restarted.
         cargo_sysroot: Option<String>    = "\"discover\"",
         /// Compilation target override (target triple).
+        // FIXME(@poliorcetics): move to multiple targets here too, but this will need more work
+        // than `checkOnSave_target`
         cargo_target: Option<String>     = "null",
         /// Unsets `#[cfg(test)]` for the specified crates.
-        cargo_unsetTest: Vec<String>   = "[\"core\"]",
+        cargo_unsetTest: Vec<String>     = "[\"core\"]",
 
         /// Check all targets and tests (`--all-targets`).
         checkOnSave_allTargets: bool                     = "true",
@@ -174,9 +176,13 @@ config_data! {
         /// ```
         /// .
         checkOnSave_overrideCommand: Option<Vec<String>> = "null",
-        /// Check for a specific target. Defaults to
-        /// `#rust-analyzer.cargo.target#`.
-        checkOnSave_target: Option<String>               = "null",
+        /// Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty.
+        ///
+        /// Can be a single target, e.g. `"x86_64-unknown-linux-gnu"` or a list of targets, e.g.
+        /// `["aarch64-apple-darwin", "x86_64-apple-darwin"]`.
+        ///
+        /// Aliased as `"checkOnSave.targets"`.
+        checkOnSave_target | checkOnSave_targets: CheckOnSaveTargets           = "[]",
 
         /// Toggles the additional completions that automatically add imports when completed.
         /// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
@@ -261,6 +267,7 @@ config_data! {
         files_excludeDirs: Vec<PathBuf> = "[]",
         /// Controls file watching implementation.
         files_watcher: FilesWatcherDef = "\"client\"",
+
         /// Enables highlighting of related references while the cursor is on `break`, `loop`, `while`, or `for` keywords.
         highlightRelated_breakPoints_enable: bool = "true",
         /// Enables highlighting of all exit points while the cursor is on any `return`, `?`, `fn`, or return type arrow (`->`).
@@ -320,6 +327,8 @@ config_data! {
         inlayHints_closingBraceHints_minLines: usize               = "25",
         /// Whether to show inlay type hints for return types of closures.
         inlayHints_closureReturnTypeHints_enable: ClosureReturnTypeHintsDef  = "\"never\"",
+        /// Whether to show inlay hints for type adjustments.
+        inlayHints_expressionAdjustmentHints_enable: AdjustmentHintsDef = "\"never\"",
         /// Whether to show inlay type hints for elided lifetimes in function signatures.
         inlayHints_lifetimeElisionHints_enable: LifetimeElisionDef = "\"never\"",
         /// Whether to prefer using parameter names as the name for elided lifetime hints if possible.
@@ -329,7 +338,8 @@ config_data! {
         /// Whether to show function parameter name inlay hints at the call
         /// site.
         inlayHints_parameterHints_enable: bool                     = "true",
-        /// Whether to show inlay type hints for compiler inserted reborrows.
+        /// Whether to show inlay hints for compiler inserted reborrows.
+        /// This setting is deprecated in favor of #rust-analyzer.inlayHints.expressionAdjustmentHints.enable#.
         inlayHints_reborrowHints_enable: ReborrowHintsDef          = "\"never\"",
         /// Whether to render leading colons for type hints, and trailing colons for parameter hints.
         inlayHints_renderColons: bool                              = "true",
@@ -1143,11 +1153,10 @@ impl Config {
             }
             Some(_) | None => FlycheckConfig::CargoCommand {
                 command: self.data.checkOnSave_command.clone(),
-                target_triple: self
-                    .data
-                    .checkOnSave_target
-                    .clone()
-                    .or_else(|| self.data.cargo_target.clone()),
+                target_triples: match &self.data.checkOnSave_target.0[..] {
+                    [] => self.data.cargo_target.clone().into_iter().collect(),
+                    targets => targets.into(),
+                },
                 all_targets: self.data.checkOnSave_allTargets,
                 no_default_features: self
                     .data
@@ -1200,10 +1209,15 @@ impl Config {
             hide_closure_initialization_hints: self
                 .data
                 .inlayHints_typeHints_hideClosureInitialization,
-            reborrow_hints: match self.data.inlayHints_reborrowHints_enable {
-                ReborrowHintsDef::Always => ide::ReborrowHints::Always,
-                ReborrowHintsDef::Never => ide::ReborrowHints::Never,
-                ReborrowHintsDef::Mutable => ide::ReborrowHints::MutableOnly,
+            adjustment_hints: match self.data.inlayHints_expressionAdjustmentHints_enable {
+                AdjustmentHintsDef::Always => ide::AdjustmentHints::Always,
+                AdjustmentHintsDef::Never => match self.data.inlayHints_reborrowHints_enable {
+                    ReborrowHintsDef::Always | ReborrowHintsDef::Mutable => {
+                        ide::AdjustmentHints::ReborrowOnly
+                    }
+                    ReborrowHintsDef::Never => ide::AdjustmentHints::Never,
+                },
+                AdjustmentHintsDef::Reborrow => ide::AdjustmentHints::ReborrowOnly,
             },
             binding_mode_hints: self.data.inlayHints_bindingModeHints_enable,
             param_names_for_lifetime_elision_hints: self
@@ -1538,6 +1552,7 @@ mod de_unit_v {
     named_unit_variant!(all);
     named_unit_variant!(skip_trivial);
     named_unit_variant!(mutable);
+    named_unit_variant!(reborrow);
     named_unit_variant!(with_block);
 }
 
@@ -1648,6 +1663,9 @@ enum InvocationStrategy {
 }
 
 #[derive(Deserialize, Debug, Clone)]
+struct CheckOnSaveTargets(#[serde(deserialize_with = "single_or_array")] Vec<String>);
+
+#[derive(Deserialize, Debug, Clone)]
 #[serde(rename_all = "snake_case")]
 enum InvocationLocation {
     Root,
@@ -1688,6 +1706,17 @@ enum ReborrowHintsDef {
 }
 
 #[derive(Deserialize, Debug, Clone)]
+#[serde(untagged)]
+enum AdjustmentHintsDef {
+    #[serde(deserialize_with = "true_or_always")]
+    Always,
+    #[serde(deserialize_with = "false_or_never")]
+    Never,
+    #[serde(deserialize_with = "de_unit_v::reborrow")]
+    Reborrow,
+}
+
+#[derive(Deserialize, Debug, Clone)]
 #[serde(rename_all = "snake_case")]
 enum FilesWatcherDef {
     Client,
@@ -1996,6 +2025,19 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
                 "Only show mutable reborrow hints."
             ]
         },
+        "AdjustmentHintsDef" => set! {
+            "type": "string",
+            "enum": [
+                "always",
+                "never",
+                "reborrow"
+            ],
+            "enumDescriptions": [
+                "Always show all adjustment hints.",
+                "Never show adjustment hints.",
+                "Only show auto borrow and dereference adjustment hints."
+            ]
+        },
         "CargoFeaturesDef" => set! {
             "anyOf": [
                 {
@@ -2084,6 +2126,17 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
                 "The command will be executed in the project root."
             ],
         },
+        "CheckOnSaveTargets" => set! {
+            "anyOf": [
+                {
+                    "type": "string",
+                },
+                {
+                    "type": "array",
+                    "items": { "type": "string" }
+                },
+            ],
+        },
         _ => panic!("missing entry for {}: {}", ty, default),
     }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs
index 189ac2fbf53..beb23c54c9f 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -359,14 +359,15 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
         .iter()
         .flat_map(|primary_span| {
             let primary_location = primary_location(config, workspace_root, primary_span, snap);
-
-            let mut message = message.clone();
-            if needs_primary_span_label {
-                if let Some(primary_span_label) = &primary_span.label {
-                    format_to!(message, "\n{}", primary_span_label);
+            let message = {
+                let mut message = message.clone();
+                if needs_primary_span_label {
+                    if let Some(primary_span_label) = &primary_span.label {
+                        format_to!(message, "\n{}", primary_span_label);
+                    }
                 }
-            }
-
+                message
+            };
             // Each primary diagnostic span may result in multiple LSP diagnostics.
             let mut diagnostics = Vec::new();
 
@@ -417,7 +418,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
                     message: message.clone(),
                     related_information: Some(information_for_additional_diagnostic),
                     tags: if tags.is_empty() { None } else { Some(tags.clone()) },
-                    data: None,
+                    data: Some(serde_json::json!({ "rendered": rd.rendered })),
                 };
                 diagnostics.push(MappedRustDiagnostic {
                     url: secondary_location.uri,
@@ -449,7 +450,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
                         }
                     },
                     tags: if tags.is_empty() { None } else { Some(tags.clone()) },
-                    data: None,
+                    data: Some(serde_json::json!({ "rendered": rd.rendered })),
                 },
                 fix: None,
             });
@@ -534,7 +535,8 @@ mod tests {
             Config::new(workspace_root.to_path_buf(), ClientCapabilities::default()),
         );
         let snap = state.snapshot();
-        let actual = map_rust_diagnostic_to_lsp(&config, &diagnostic, workspace_root, &snap);
+        let mut actual = map_rust_diagnostic_to_lsp(&config, &diagnostic, workspace_root, &snap);
+        actual.iter_mut().for_each(|diag| diag.diagnostic.data = None);
         expect.assert_debug_eq(&actual)
     }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/from_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/from_proto.rs
index 936957bab48..dd433b0f4d3 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/from_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/from_proto.rs
@@ -42,8 +42,10 @@ pub(crate) fn offset(line_index: &LineIndex, position: lsp_types::Position) -> R
 pub(crate) fn text_range(line_index: &LineIndex, range: lsp_types::Range) -> Result<TextRange> {
     let start = offset(line_index, range.start)?;
     let end = offset(line_index, range.end)?;
-    let text_range = TextRange::new(start, end);
-    Ok(text_range)
+    match end < start {
+        true => Err(format_err!("Invalid Range").into()),
+        false => Ok(TextRange::new(start, end)),
+    }
 }
 
 pub(crate) fn file_id(snap: &GlobalStateSnapshot, url: &lsp_types::Url) -> Result<FileId> {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index 74277ff2e57..4e8bc8d6462 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -100,7 +100,7 @@ pub(crate) struct GlobalState {
     /// the user just adds comments or whitespace to Cargo.toml, we do not want
     /// to invalidate any salsa caches.
     pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
-    pub(crate) fetch_workspaces_queue: OpQueue<Vec<anyhow::Result<ProjectWorkspace>>>,
+    pub(crate) fetch_workspaces_queue: OpQueue<Option<Vec<anyhow::Result<ProjectWorkspace>>>>,
     pub(crate) fetch_build_data_queue:
         OpQueue<(Arc<Vec<ProjectWorkspace>>, Vec<anyhow::Result<WorkspaceBuildScripts>>)>,
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs
index 34795a8eb40..d190a9f4e2c 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs
@@ -9,9 +9,9 @@ use std::{
 
 use anyhow::Context;
 use ide::{
-    AnnotationConfig, AssistKind, AssistResolveStrategy, FileId, FilePosition, FileRange,
-    HoverAction, HoverGotoTypeData, Query, RangeInfo, ReferenceCategory, Runnable, RunnableKind,
-    SingleResolve, SourceChange, TextEdit,
+    AnnotationConfig, AssistKind, AssistResolveStrategy, Cancellable, FileId, FilePosition,
+    FileRange, HoverAction, HoverGotoTypeData, Query, RangeInfo, ReferenceCategory, Runnable,
+    RunnableKind, SingleResolve, SourceChange, TextEdit,
 };
 use ide_db::SymbolKind;
 use lsp_server::ErrorCode;
@@ -556,7 +556,7 @@ pub(crate) fn handle_will_rename_files(
     if source_change.source_file_edits.is_empty() {
         Ok(None)
     } else {
-        to_proto::workspace_edit(&snap, source_change).map(Some)
+        Ok(Some(to_proto::workspace_edit(&snap, source_change)?))
     }
 }
 
@@ -1313,7 +1313,7 @@ pub(crate) fn handle_ssr(
         position,
         selections,
     )??;
-    to_proto::workspace_edit(&snap, source_change)
+    to_proto::workspace_edit(&snap, source_change).map_err(Into::into)
 }
 
 pub(crate) fn publish_diagnostics(
@@ -1354,13 +1354,12 @@ pub(crate) fn handle_inlay_hints(
 ) -> Result<Option<Vec<InlayHint>>> {
     let _p = profile::span("handle_inlay_hints");
     let document_uri = &params.text_document.uri;
-    let file_id = from_proto::file_id(&snap, document_uri)?;
-    let line_index = snap.file_line_index(file_id)?;
-    let range = from_proto::file_range(
+    let FileRange { file_id, range } = from_proto::file_range(
         &snap,
         TextDocumentIdentifier::new(document_uri.to_owned()),
         params.range,
     )?;
+    let line_index = snap.file_line_index(file_id)?;
     let inlay_hints_config = snap.config.inlay_hints();
     Ok(Some(
         snap.analysis
@@ -1369,7 +1368,7 @@ pub(crate) fn handle_inlay_hints(
             .map(|it| {
                 to_proto::inlay_hint(&snap, &line_index, inlay_hints_config.render_colons, it)
             })
-            .collect::<Result<Vec<_>>>()?,
+            .collect::<Cancellable<Vec<_>>>()?,
     ))
 }
 
@@ -1426,7 +1425,7 @@ pub(crate) fn handle_call_hierarchy_prepare(
         .into_iter()
         .filter(|it| it.kind == Some(SymbolKind::Function))
         .map(|it| to_proto::call_hierarchy_item(&snap, it))
-        .collect::<Result<Vec<_>>>()?;
+        .collect::<Cancellable<Vec<_>>>()?;
 
     Ok(Some(res))
 }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/line_index.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/line_index.rs
index 0d424b91570..2945dba12f2 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/line_index.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/line_index.rs
@@ -27,10 +27,6 @@ pub(crate) enum LineEndings {
 impl LineEndings {
     /// Replaces `\r\n` with `\n` in-place in `src`.
     pub(crate) fn normalize(src: String) -> (String, LineEndings) {
-        if !src.as_bytes().contains(&b'\r') {
-            return (src, LineEndings::Unix);
-        }
-
         // We replace `\r\n` with `\n` in-place, which doesn't break utf-8 encoding.
         // While we *can* call `as_mut_vec` and do surgery on the live string
         // directly, let's rather steal the contents of `src`. This makes the code
@@ -39,10 +35,19 @@ impl LineEndings {
         let mut buf = src.into_bytes();
         let mut gap_len = 0;
         let mut tail = buf.as_mut_slice();
+        let mut crlf_seen = false;
+
+        let find_crlf = |src: &[u8]| src.windows(2).position(|it| it == b"\r\n");
+
         loop {
             let idx = match find_crlf(&tail[gap_len..]) {
-                None => tail.len(),
-                Some(idx) => idx + gap_len,
+                None if crlf_seen => tail.len(),
+                // SAFETY: buf is unchanged and therefore still contains utf8 data
+                None => return (unsafe { String::from_utf8_unchecked(buf) }, LineEndings::Unix),
+                Some(idx) => {
+                    crlf_seen = true;
+                    idx + gap_len
+                }
             };
             tail.copy_within(gap_len..idx, 0);
             tail = &mut tail[idx - gap_len..];
@@ -54,15 +59,48 @@ impl LineEndings {
 
         // Account for removed `\r`.
         // After `set_len`, `buf` is guaranteed to contain utf-8 again.
-        let new_len = buf.len() - gap_len;
         let src = unsafe {
+            let new_len = buf.len() - gap_len;
             buf.set_len(new_len);
             String::from_utf8_unchecked(buf)
         };
-        return (src, LineEndings::Dos);
+        (src, LineEndings::Dos)
+    }
+}
 
-        fn find_crlf(src: &[u8]) -> Option<usize> {
-            src.windows(2).position(|it| it == b"\r\n")
-        }
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn unix() {
+        let src = "a\nb\nc\n\n\n\n";
+        let (res, endings) = LineEndings::normalize(src.into());
+        assert_eq!(endings, LineEndings::Unix);
+        assert_eq!(res, src);
+    }
+
+    #[test]
+    fn dos() {
+        let src = "\r\na\r\n\r\nb\r\nc\r\n\r\n\r\n\r\n";
+        let (res, endings) = LineEndings::normalize(src.into());
+        assert_eq!(endings, LineEndings::Dos);
+        assert_eq!(res, "\na\n\nb\nc\n\n\n\n");
+    }
+
+    #[test]
+    fn mixed() {
+        let src = "a\r\nb\r\nc\r\n\n\r\n\n";
+        let (res, endings) = LineEndings::normalize(src.into());
+        assert_eq!(endings, LineEndings::Dos);
+        assert_eq!(res, "a\nb\nc\n\n\n\n");
+    }
+
+    #[test]
+    fn none() {
+        let src = "abc";
+        let (res, endings) = LineEndings::normalize(src.into());
+        assert_eq!(endings, LineEndings::Unix);
+        assert_eq!(res, src);
     }
 }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_utils.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_utils.rs
index c6a4db9a453..0971dc36f3a 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_utils.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_utils.rs
@@ -1,5 +1,5 @@
 //! Utilities for LSP-related boilerplate code.
-use std::{ops::Range, sync::Arc};
+use std::{mem, ops::Range, sync::Arc};
 
 use lsp_server::Notification;
 
@@ -133,11 +133,37 @@ impl GlobalState {
 }
 
 pub(crate) fn apply_document_changes(
-    old_text: &mut String,
-    content_changes: Vec<lsp_types::TextDocumentContentChangeEvent>,
-) {
+    file_contents: impl FnOnce() -> String,
+    mut content_changes: Vec<lsp_types::TextDocumentContentChangeEvent>,
+) -> String {
+    // Skip to the last full document change, as it invalidates all previous changes anyways.
+    let mut start = content_changes
+        .iter()
+        .rev()
+        .position(|change| change.range.is_none())
+        .map(|idx| content_changes.len() - idx - 1)
+        .unwrap_or(0);
+
+    let mut text: String = match content_changes.get_mut(start) {
+        // peek at the first content change as an optimization
+        Some(lsp_types::TextDocumentContentChangeEvent { range: None, text, .. }) => {
+            let text = mem::take(text);
+            start += 1;
+
+            // The only change is a full document update
+            if start == content_changes.len() {
+                return text;
+            }
+            text
+        }
+        Some(_) => file_contents(),
+        // we received no content changes
+        None => return file_contents(),
+    };
+
     let mut line_index = LineIndex {
-        index: Arc::new(ide::LineIndex::new(old_text)),
+        // the index will be overwritten in the bottom loop's first iteration
+        index: Arc::new(ide::LineIndex::new(&text)),
         // We don't care about line endings or offset encoding here.
         endings: LineEndings::Unix,
         encoding: PositionEncoding::Utf16,
@@ -148,38 +174,20 @@ pub(crate) fn apply_document_changes(
     // Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we
     // remember the last valid line in the index and only rebuild it if needed.
     // The VFS will normalize the end of lines to `\n`.
-    enum IndexValid {
-        All,
-        UpToLineExclusive(u32),
-    }
-
-    impl IndexValid {
-        fn covers(&self, line: u32) -> bool {
-            match *self {
-                IndexValid::UpToLineExclusive(to) => to > line,
-                _ => true,
-            }
-        }
-    }
-
-    let mut index_valid = IndexValid::All;
+    let mut index_valid = !0u32;
     for change in content_changes {
-        match change.range {
-            Some(range) => {
-                if !index_valid.covers(range.end.line) {
-                    line_index.index = Arc::new(ide::LineIndex::new(old_text));
-                }
-                index_valid = IndexValid::UpToLineExclusive(range.start.line);
-                if let Ok(range) = from_proto::text_range(&line_index, range) {
-                    old_text.replace_range(Range::<usize>::from(range), &change.text);
-                }
+        // The None case can't happen as we have handled it above already
+        if let Some(range) = change.range {
+            if index_valid <= range.end.line {
+                *Arc::make_mut(&mut line_index.index) = ide::LineIndex::new(&text);
             }
-            None => {
-                *old_text = change.text;
-                index_valid = IndexValid::UpToLineExclusive(0);
+            index_valid = range.start.line;
+            if let Ok(range) = from_proto::text_range(&line_index, range) {
+                text.replace_range(Range::<usize>::from(range), &change.text);
             }
         }
     }
+    text
 }
 
 /// Checks that the edits inside the completion and the additional edits do not overlap.
@@ -242,11 +250,10 @@ mod tests {
             };
         }
 
-        let mut text = String::new();
-        apply_document_changes(&mut text, vec![]);
+        let text = apply_document_changes(|| String::new(), vec![]);
         assert_eq!(text, "");
-        apply_document_changes(
-            &mut text,
+        let text = apply_document_changes(
+            || text,
             vec![TextDocumentContentChangeEvent {
                 range: None,
                 range_length: None,
@@ -254,39 +261,39 @@ mod tests {
             }],
         );
         assert_eq!(text, "the");
-        apply_document_changes(&mut text, c![0, 3; 0, 3 => " quick"]);
+        let text = apply_document_changes(|| text, c![0, 3; 0, 3 => " quick"]);
         assert_eq!(text, "the quick");
-        apply_document_changes(&mut text, c![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]);
+        let text = apply_document_changes(|| text, c![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]);
         assert_eq!(text, "quick foxes");
-        apply_document_changes(&mut text, c![0, 11; 0, 11 => "\ndream"]);
+        let text = apply_document_changes(|| text, c![0, 11; 0, 11 => "\ndream"]);
         assert_eq!(text, "quick foxes\ndream");
-        apply_document_changes(&mut text, c![1, 0; 1, 0 => "have "]);
+        let text = apply_document_changes(|| text, c![1, 0; 1, 0 => "have "]);
         assert_eq!(text, "quick foxes\nhave dream");
-        apply_document_changes(
-            &mut text,
+        let text = apply_document_changes(
+            || text,
             c![0, 0; 0, 0 => "the ", 1, 4; 1, 4 => " quiet", 1, 16; 1, 16 => "s\n"],
         );
         assert_eq!(text, "the quick foxes\nhave quiet dreams\n");
-        apply_document_changes(&mut text, c![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"]);
+        let text = apply_document_changes(|| text, c![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"]);
         assert_eq!(text, "the quick foxes\n\nhave quiet dreams\n\n");
-        apply_document_changes(
-            &mut text,
+        let text = apply_document_changes(
+            || text,
             c![1, 0; 1, 0 => "DREAM", 2, 0; 2, 0 => "they ", 3, 0; 3, 0 => "DON'T THEY?"],
         );
         assert_eq!(text, "the quick foxes\nDREAM\nthey have quiet dreams\nDON'T THEY?\n");
-        apply_document_changes(&mut text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]);
+        let text = apply_document_changes(|| text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]);
         assert_eq!(text, "the quick \nthey have quiet dreams\n");
 
-        text = String::from("❤️");
-        apply_document_changes(&mut text, c![0, 0; 0, 0 => "a"]);
+        let text = String::from("❤️");
+        let text = apply_document_changes(|| text, c![0, 0; 0, 0 => "a"]);
         assert_eq!(text, "a❤️");
 
-        text = String::from("a\nb");
-        apply_document_changes(&mut text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]);
+        let text = String::from("a\nb");
+        let text = apply_document_changes(|| text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]);
         assert_eq!(text, "adcb");
 
-        text = String::from("a\nb");
-        apply_document_changes(&mut text, c![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]);
+        let text = String::from("a\nb");
+        let text = apply_document_changes(|| text, c![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]);
         assert_eq!(text, "ațc\ncb");
     }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index 7d10dc5d15b..274588ce0e0 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
@@ -451,7 +451,7 @@ impl GlobalState {
                     ProjectWorkspaceProgress::Begin => (Progress::Begin, None),
                     ProjectWorkspaceProgress::Report(msg) => (Progress::Report, Some(msg)),
                     ProjectWorkspaceProgress::End(workspaces) => {
-                        self.fetch_workspaces_queue.op_completed(workspaces);
+                        self.fetch_workspaces_queue.op_completed(Some(workspaces));
 
                         let old = Arc::clone(&self.workspaces);
                         self.switch_workspaces("fetched workspace".to_string());
@@ -759,8 +759,10 @@ impl GlobalState {
 
                     let vfs = &mut this.vfs.write().0;
                     let file_id = vfs.file_id(&path).unwrap();
-                    let mut text = String::from_utf8(vfs.file_contents(file_id).to_vec()).unwrap();
-                    apply_document_changes(&mut text, params.content_changes);
+                    let text = apply_document_changes(
+                        || std::str::from_utf8(vfs.file_contents(file_id)).unwrap().into(),
+                        params.content_changes,
+                    );
 
                     vfs.set_file_contents(path, Some(text.into_bytes()));
                 }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/mem_docs.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/mem_docs.rs
index f86a0f66ad8..45a1dab9772 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/mem_docs.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/mem_docs.rs
@@ -7,7 +7,7 @@ use vfs::VfsPath;
 
 /// Holds the set of in-memory documents.
 ///
-/// For these document, there true contents is maintained by the client. It
+/// For these document, their true contents is maintained by the client. It
 /// might be different from what's on disk.
 #[derive(Default, Clone)]
 pub(crate) struct MemDocs {
@@ -19,6 +19,7 @@ impl MemDocs {
     pub(crate) fn contains(&self, path: &VfsPath) -> bool {
         self.mem_docs.contains_key(path)
     }
+
     pub(crate) fn insert(&mut self, path: VfsPath, data: DocumentData) -> Result<(), ()> {
         self.added_or_removed = true;
         match self.mem_docs.insert(path, data) {
@@ -26,6 +27,7 @@ impl MemDocs {
             None => Ok(()),
         }
     }
+
     pub(crate) fn remove(&mut self, path: &VfsPath) -> Result<(), ()> {
         self.added_or_removed = true;
         match self.mem_docs.remove(path) {
@@ -33,17 +35,21 @@ impl MemDocs {
             None => Err(()),
         }
     }
+
     pub(crate) fn get(&self, path: &VfsPath) -> Option<&DocumentData> {
         self.mem_docs.get(path)
     }
+
     pub(crate) fn get_mut(&mut self, path: &VfsPath) -> Option<&mut DocumentData> {
         // NB: don't set `self.added_or_removed` here, as that purposefully only
         // tracks changes to the key set.
         self.mem_docs.get_mut(path)
     }
+
     pub(crate) fn iter(&self) -> impl Iterator<Item = &VfsPath> {
         self.mem_docs.keys()
     }
+
     pub(crate) fn take_changes(&mut self) -> bool {
         mem::replace(&mut self.added_or_removed, false)
     }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index e1f651786de..fcfe4be0b8c 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -106,6 +106,14 @@ impl GlobalState {
             status.health = lsp_ext::Health::Error;
             status.message = Some(error)
         }
+
+        if self.config.linked_projects().is_empty()
+            && self.config.detached_files().is_empty()
+            && self.config.notifications().cargo_toml_not_found
+        {
+            status.health = lsp_ext::Health::Warning;
+            status.message = Some("Workspace reload required".to_string())
+        }
         status
     }
 
@@ -198,12 +206,9 @@ impl GlobalState {
             self.show_and_log_error("failed to run build scripts".to_string(), Some(error));
         }
 
-        let workspaces = self
-            .fetch_workspaces_queue
-            .last_op_result()
-            .iter()
-            .filter_map(|res| res.as_ref().ok().cloned())
-            .collect::<Vec<_>>();
+        let Some(workspaces) = self.fetch_workspaces_queue.last_op_result() else { return; };
+        let workspaces =
+            workspaces.iter().filter_map(|res| res.as_ref().ok().cloned()).collect::<Vec<_>>();
 
         fn eq_ignore_build_data<'a>(
             left: &'a ProjectWorkspace,
@@ -300,9 +305,6 @@ impl GlobalState {
         let files_config = self.config.files();
         let project_folders = ProjectFolders::new(&self.workspaces, &files_config.exclude);
 
-        let standalone_server_name =
-            format!("rust-analyzer-proc-macro-srv{}", std::env::consts::EXE_SUFFIX);
-
         if self.proc_macro_clients.is_empty() {
             if let Some((path, path_manually_set)) = self.config.proc_macro_srv() {
                 tracing::info!("Spawning proc-macro servers");
@@ -310,40 +312,17 @@ impl GlobalState {
                     .workspaces
                     .iter()
                     .map(|ws| {
-                        let (path, args) = if path_manually_set {
+                        let (path, args): (_, &[_]) = if path_manually_set {
                             tracing::debug!(
                                 "Pro-macro server path explicitly set: {}",
                                 path.display()
                             );
-                            (path.clone(), vec![])
+                            (path.clone(), &[])
                         } else {
-                            let mut sysroot_server = None;
-                            if let ProjectWorkspace::Cargo { sysroot, .. }
-                            | ProjectWorkspace::Json { sysroot, .. } = ws
-                            {
-                                if let Some(sysroot) = sysroot.as_ref() {
-                                    let server_path = sysroot
-                                        .root()
-                                        .join("libexec")
-                                        .join(&standalone_server_name);
-                                    if std::fs::metadata(&server_path).is_ok() {
-                                        tracing::debug!(
-                                            "Sysroot proc-macro server exists at {}",
-                                            server_path.display()
-                                        );
-                                        sysroot_server = Some(server_path);
-                                    } else {
-                                        tracing::debug!(
-                                            "Sysroot proc-macro server does not exist at {}",
-                                            server_path.display()
-                                        );
-                                    }
-                                }
+                            match ws.find_sysroot_proc_macro_srv() {
+                                Some(server_path) => (server_path, &[]),
+                                None => (path.clone(), &["proc-macro"]),
                             }
-                            sysroot_server.map_or_else(
-                                || (path.clone(), vec!["proc-macro".to_owned()]),
-                                |path| (path, vec![]),
-                            )
                         };
 
                         tracing::info!(?args, "Using proc-macro server at {}", path.display(),);
@@ -427,9 +406,14 @@ impl GlobalState {
     fn fetch_workspace_error(&self) -> Result<(), String> {
         let mut buf = String::new();
 
-        for ws in self.fetch_workspaces_queue.last_op_result() {
-            if let Err(err) = ws {
-                stdx::format_to!(buf, "rust-analyzer failed to load workspace: {:#}\n", err);
+        let Some(last_op_result) = self.fetch_workspaces_queue.last_op_result() else { return Ok(()) };
+        if last_op_result.is_empty() {
+            stdx::format_to!(buf, "rust-analyzer failed to discover workspace");
+        } else {
+            for ws in last_op_result {
+                if let Err(err) = ws {
+                    stdx::format_to!(buf, "rust-analyzer failed to load workspace: {:#}\n", err);
+                }
             }
         }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
index 6c84a2069cd..81cc1952ba5 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
@@ -24,7 +24,7 @@ use crate::{
     line_index::{LineEndings, LineIndex, PositionEncoding},
     lsp_ext,
     lsp_utils::invalid_params_error,
-    semantic_tokens, Result,
+    semantic_tokens,
 };
 
 pub(crate) fn position(line_index: &LineIndex, offset: TextSize) -> lsp_types::Position {
@@ -429,7 +429,7 @@ pub(crate) fn inlay_hint(
     line_index: &LineIndex,
     render_colons: bool,
     mut inlay_hint: InlayHint,
-) -> Result<lsp_types::InlayHint> {
+) -> Cancellable<lsp_types::InlayHint> {
     match inlay_hint.kind {
         InlayKind::ParameterHint if render_colons => inlay_hint.label.append_str(":"),
         InlayKind::TypeHint if render_colons => inlay_hint.label.prepend_str(": "),
@@ -440,32 +440,35 @@ pub(crate) fn inlay_hint(
     Ok(lsp_types::InlayHint {
         position: match inlay_hint.kind {
             // before annotated thing
-            InlayKind::ParameterHint
-            | InlayKind::ImplicitReborrowHint
-            | InlayKind::BindingModeHint => position(line_index, inlay_hint.range.start()),
+            InlayKind::ParameterHint | InlayKind::AdjustmentHint | InlayKind::BindingModeHint => {
+                position(line_index, inlay_hint.range.start())
+            }
             // after annotated thing
             InlayKind::ClosureReturnTypeHint
             | InlayKind::TypeHint
             | InlayKind::ChainingHint
             | InlayKind::GenericParamListHint
+            | InlayKind::AdjustmentHintClosingParenthesis
             | InlayKind::LifetimeHint
             | InlayKind::ClosingBraceHint => position(line_index, inlay_hint.range.end()),
         },
         padding_left: Some(match inlay_hint.kind {
             InlayKind::TypeHint => !render_colons,
             InlayKind::ChainingHint | InlayKind::ClosingBraceHint => true,
-            InlayKind::BindingModeHint
+            InlayKind::AdjustmentHintClosingParenthesis
+            | InlayKind::BindingModeHint
             | InlayKind::ClosureReturnTypeHint
             | InlayKind::GenericParamListHint
-            | InlayKind::ImplicitReborrowHint
+            | InlayKind::AdjustmentHint
             | InlayKind::LifetimeHint
             | InlayKind::ParameterHint => false,
         }),
         padding_right: Some(match inlay_hint.kind {
-            InlayKind::ChainingHint
+            InlayKind::AdjustmentHintClosingParenthesis
+            | InlayKind::ChainingHint
             | InlayKind::ClosureReturnTypeHint
             | InlayKind::GenericParamListHint
-            | InlayKind::ImplicitReborrowHint
+            | InlayKind::AdjustmentHint
             | InlayKind::TypeHint
             | InlayKind::ClosingBraceHint => false,
             InlayKind::BindingModeHint => inlay_hint.label.as_simple_str() != Some("&"),
@@ -476,10 +479,11 @@ pub(crate) fn inlay_hint(
             InlayKind::ClosureReturnTypeHint | InlayKind::TypeHint | InlayKind::ChainingHint => {
                 Some(lsp_types::InlayHintKind::TYPE)
             }
-            InlayKind::BindingModeHint
+            InlayKind::AdjustmentHintClosingParenthesis
+            | InlayKind::BindingModeHint
             | InlayKind::GenericParamListHint
             | InlayKind::LifetimeHint
-            | InlayKind::ImplicitReborrowHint
+            | InlayKind::AdjustmentHint
             | InlayKind::ClosingBraceHint => None,
         },
         text_edits: None,
@@ -518,7 +522,7 @@ pub(crate) fn inlay_hint(
 fn inlay_hint_label(
     snap: &GlobalStateSnapshot,
     label: InlayHintLabel,
-) -> Result<lsp_types::InlayHintLabel> {
+) -> Cancellable<lsp_types::InlayHintLabel> {
     Ok(match label.as_simple_str() {
         Some(s) => lsp_types::InlayHintLabel::String(s.into()),
         None => lsp_types::InlayHintLabel::LabelParts(
@@ -536,7 +540,7 @@ fn inlay_hint_label(
                         command: None,
                     })
                 })
-                .collect::<Result<Vec<_>>>()?,
+                .collect::<Cancellable<Vec<_>>>()?,
         ),
     })
 }
@@ -794,7 +798,7 @@ pub(crate) fn optional_versioned_text_document_identifier(
 pub(crate) fn location(
     snap: &GlobalStateSnapshot,
     frange: FileRange,
-) -> Result<lsp_types::Location> {
+) -> Cancellable<lsp_types::Location> {
     let url = url(snap, frange.file_id);
     let line_index = snap.file_line_index(frange.file_id)?;
     let range = range(&line_index, frange.range);
@@ -806,7 +810,7 @@ pub(crate) fn location(
 pub(crate) fn location_from_nav(
     snap: &GlobalStateSnapshot,
     nav: NavigationTarget,
-) -> Result<lsp_types::Location> {
+) -> Cancellable<lsp_types::Location> {
     let url = url(snap, nav.file_id);
     let line_index = snap.file_line_index(nav.file_id)?;
     let range = range(&line_index, nav.full_range);
@@ -818,7 +822,7 @@ pub(crate) fn location_link(
     snap: &GlobalStateSnapshot,
     src: Option<FileRange>,
     target: NavigationTarget,
-) -> Result<lsp_types::LocationLink> {
+) -> Cancellable<lsp_types::LocationLink> {
     let origin_selection_range = match src {
         Some(src) => {
             let line_index = snap.file_line_index(src.file_id)?;
@@ -840,7 +844,7 @@ pub(crate) fn location_link(
 fn location_info(
     snap: &GlobalStateSnapshot,
     target: NavigationTarget,
-) -> Result<(lsp_types::Url, lsp_types::Range, lsp_types::Range)> {
+) -> Cancellable<(lsp_types::Url, lsp_types::Range, lsp_types::Range)> {
     let line_index = snap.file_line_index(target.file_id)?;
 
     let target_uri = url(snap, target.file_id);
@@ -854,12 +858,12 @@ pub(crate) fn goto_definition_response(
     snap: &GlobalStateSnapshot,
     src: Option<FileRange>,
     targets: Vec<NavigationTarget>,
-) -> Result<lsp_types::GotoDefinitionResponse> {
+) -> Cancellable<lsp_types::GotoDefinitionResponse> {
     if snap.config.location_link() {
         let links = targets
             .into_iter()
             .map(|nav| location_link(snap, src, nav))
-            .collect::<Result<Vec<_>>>()?;
+            .collect::<Cancellable<Vec<_>>>()?;
         Ok(links.into())
     } else {
         let locations = targets
@@ -867,7 +871,7 @@ pub(crate) fn goto_definition_response(
             .map(|nav| {
                 location(snap, FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() })
             })
-            .collect::<Result<Vec<_>>>()?;
+            .collect::<Cancellable<Vec<_>>>()?;
         Ok(locations.into())
     }
 }
@@ -881,7 +885,7 @@ pub(crate) fn snippet_text_document_edit(
     is_snippet: bool,
     file_id: FileId,
     edit: TextEdit,
-) -> Result<lsp_ext::SnippetTextDocumentEdit> {
+) -> Cancellable<lsp_ext::SnippetTextDocumentEdit> {
     let text_document = optional_versioned_text_document_identifier(snap, file_id);
     let line_index = snap.file_line_index(file_id)?;
     let mut edits: Vec<_> =
@@ -958,7 +962,7 @@ pub(crate) fn snippet_text_document_ops(
 pub(crate) fn snippet_workspace_edit(
     snap: &GlobalStateSnapshot,
     source_change: SourceChange,
-) -> Result<lsp_ext::SnippetWorkspaceEdit> {
+) -> Cancellable<lsp_ext::SnippetWorkspaceEdit> {
     let mut document_changes: Vec<lsp_ext::SnippetDocumentChangeOperation> = Vec::new();
 
     for op in source_change.file_system_edits {
@@ -995,7 +999,7 @@ pub(crate) fn snippet_workspace_edit(
 pub(crate) fn workspace_edit(
     snap: &GlobalStateSnapshot,
     source_change: SourceChange,
-) -> Result<lsp_types::WorkspaceEdit> {
+) -> Cancellable<lsp_types::WorkspaceEdit> {
     assert!(!source_change.is_snippet);
     snippet_workspace_edit(snap, source_change).map(|it| it.into())
 }
@@ -1048,7 +1052,7 @@ impl From<lsp_ext::SnippetTextEdit>
 pub(crate) fn call_hierarchy_item(
     snap: &GlobalStateSnapshot,
     target: NavigationTarget,
-) -> Result<lsp_types::CallHierarchyItem> {
+) -> Cancellable<lsp_types::CallHierarchyItem> {
     let name = target.name.to_string();
     let detail = target.description.clone();
     let kind = target.kind.map(symbol_kind).unwrap_or(lsp_types::SymbolKind::FUNCTION);
@@ -1080,7 +1084,7 @@ pub(crate) fn code_action(
     snap: &GlobalStateSnapshot,
     assist: Assist,
     resolve_data: Option<(usize, lsp_types::CodeActionParams)>,
-) -> Result<lsp_ext::CodeAction> {
+) -> Cancellable<lsp_ext::CodeAction> {
     let mut res = lsp_ext::CodeAction {
         title: assist.label.to_string(),
         group: assist.group.filter(|_| snap.config.code_action_group()).map(|gr| gr.0),
@@ -1113,13 +1117,13 @@ pub(crate) fn code_action(
 pub(crate) fn runnable(
     snap: &GlobalStateSnapshot,
     runnable: Runnable,
-) -> Result<lsp_ext::Runnable> {
+) -> Cancellable<lsp_ext::Runnable> {
     let config = snap.config.runnables();
     let spec = CargoTargetSpec::for_file(snap, runnable.nav.file_id)?;
     let workspace_root = spec.as_ref().map(|it| it.workspace_root.clone());
     let target = spec.as_ref().map(|s| s.target.clone());
     let (cargo_args, executable_args) =
-        CargoTargetSpec::runnable_args(snap, spec, &runnable.kind, &runnable.cfg)?;
+        CargoTargetSpec::runnable_args(snap, spec, &runnable.kind, &runnable.cfg);
     let label = runnable.label(target);
     let location = location_link(snap, None, runnable.nav)?;
 
@@ -1142,7 +1146,7 @@ pub(crate) fn code_lens(
     acc: &mut Vec<lsp_types::CodeLens>,
     snap: &GlobalStateSnapshot,
     annotation: Annotation,
-) -> Result<()> {
+) -> Cancellable<()> {
     let client_commands_config = snap.config.client_commands();
     match annotation.kind {
         AnnotationKind::Runnable(run) => {
diff --git a/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml b/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml
index e75867e2d81..593dc4e55b2 100644
--- a/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/stdx/Cargo.toml b/src/tools/rust-analyzer/crates/stdx/Cargo.toml
index e0657ab0f6d..f7b7d09640f 100644
--- a/src/tools/rust-analyzer/crates/stdx/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/stdx/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
@@ -16,7 +16,7 @@ always-assert = { version = "0.1.2", features = ["log"] }
 # Think twice before adding anything here
 
 [target.'cfg(windows)'.dependencies]
-miow = "0.4.0"
+miow = "0.5.0"
 winapi = { version = "0.3.9", features = ["winerror"] }
 
 [features]
diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
index 1ef903371cf..00743cca559 100644
--- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
@@ -5,7 +5,7 @@ description = "Comment and whitespace preserving parser for the Rust language"
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-lang/rust-analyzer"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml
index ba2f515b0bc..f295c40065d 100644
--- a/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml
@@ -4,7 +4,7 @@ name = "syntax-fuzz"
 version = "0.0.1"
 publish = false
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [package.metadata]
 cargo-fuzz = true
diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram
index 5379732ac6c..0a0cb0290d6 100644
--- a/src/tools/rust-analyzer/crates/syntax/rust.ungram
+++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram
@@ -239,8 +239,11 @@ Static =
 Trait =
   Attr* Visibility?
   'unsafe'? 'auto'?
-  'trait' Name GenericParamList? (':' TypeBoundList?)? WhereClause?
-  AssocItemList
+  'trait' Name GenericParamList?
+  (
+    (':' TypeBoundList?)? WhereClause? AssocItemList
+    | '=' TypeBoundList? WhereClause? ';'
+  )
 
 AssocItemList =
   '{' Attr* AssocItem* '}'
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
index 6cfb98d92fc..2ea715f47fb 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
@@ -407,6 +407,8 @@ impl Trait {
     pub fn auto_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![auto]) }
     pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) }
     pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
index ba72e64425b..8990f7a7d4e 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
@@ -209,17 +209,19 @@ impl ast::String {
         let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
 
         let mut buf = String::new();
-        let mut text_iter = text.chars();
+        let mut prev_end = 0;
         let mut has_error = false;
         unescape_literal(text, Mode::Str, &mut |char_range, unescaped_char| match (
             unescaped_char,
             buf.capacity() == 0,
         ) {
             (Ok(c), false) => buf.push(c),
-            (Ok(c), true) if char_range.len() == 1 && Some(c) == text_iter.next() => (),
+            (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
+                prev_end = char_range.end
+            }
             (Ok(c), true) => {
                 buf.reserve_exact(text.len());
-                buf.push_str(&text[..char_range.start]);
+                buf.push_str(&text[..prev_end]);
                 buf.push(c);
             }
             (Err(_), _) => has_error = true,
@@ -252,17 +254,19 @@ impl ast::ByteString {
         let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
 
         let mut buf: Vec<u8> = Vec::new();
-        let mut text_iter = text.chars();
+        let mut prev_end = 0;
         let mut has_error = false;
         unescape_literal(text, Mode::ByteStr, &mut |char_range, unescaped_char| match (
             unescaped_char,
             buf.capacity() == 0,
         ) {
             (Ok(c), false) => buf.push(c as u8),
-            (Ok(c), true) if char_range.len() == 1 && Some(c) == text_iter.next() => (),
+            (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
+                prev_end = char_range.end
+            }
             (Ok(c), true) => {
                 buf.reserve_exact(text.len());
-                buf.extend_from_slice(text[..char_range.start].as_bytes());
+                buf.extend_from_slice(text[..prev_end].as_bytes());
                 buf.push(c as u8);
             }
             (Err(_), _) => has_error = true,
@@ -445,6 +449,36 @@ mod tests {
         check_string_value(r"\foobar", None);
         check_string_value(r"\nfoobar", "\nfoobar");
         check_string_value(r"C:\\Windows\\System32\\", "C:\\Windows\\System32\\");
+        check_string_value(r"\x61bcde", "abcde");
+        check_string_value(
+            r"a\
+bcde", "abcde",
+        );
+    }
+
+    fn check_byte_string_value<'a, const N: usize>(
+        lit: &str,
+        expected: impl Into<Option<&'a [u8; N]>>,
+    ) {
+        assert_eq!(
+            ast::ByteString { syntax: make::tokens::literal(&format!("b\"{}\"", lit)) }
+                .value()
+                .as_deref(),
+            expected.into().map(|value| &value[..])
+        );
+    }
+
+    #[test]
+    fn test_byte_string_escape() {
+        check_byte_string_value(r"foobar", b"foobar");
+        check_byte_string_value(r"\foobar", None::<&[u8; 0]>);
+        check_byte_string_value(r"\nfoobar", b"\nfoobar");
+        check_byte_string_value(r"C:\\Windows\\System32\\", b"C:\\Windows\\System32\\");
+        check_byte_string_value(r"\x61bcde", b"abcde");
+        check_byte_string_value(
+            r"a\
+bcde", b"abcde",
+        );
     }
 
     #[test]
diff --git a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
index cceafe04e37..1047373b1c7 100644
--- a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/text-edit/Cargo.toml b/src/tools/rust-analyzer/crates/text-edit/Cargo.toml
index 7a90d64a98b..8df7e1af611 100644
--- a/src/tools/rust-analyzer/crates/text-edit/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/text-edit/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
index 3e0f31f19c5..a6a3ae742ae 100644
--- a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/tt/Cargo.toml b/src/tools/rust-analyzer/crates/tt/Cargo.toml
index 52dfb860804..4f2103f3a97 100644
--- a/src/tools/rust-analyzer/crates/tt/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/tt/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
index df5dc24e2cd..061f3c157a8 100644
--- a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/crates/vfs/Cargo.toml b/src/tools/rust-analyzer/crates/vfs/Cargo.toml
index d7549a28415..e55bf6f293c 100644
--- a/src/tools/rust-analyzer/crates/vfs/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/vfs/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 description = "TBD"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [lib]
 doctest = false
diff --git a/src/tools/rust-analyzer/docs/dev/architecture.md b/src/tools/rust-analyzer/docs/dev/architecture.md
index e3a4fdfda90..a07cf036e06 100644
--- a/src/tools/rust-analyzer/docs/dev/architecture.md
+++ b/src/tools/rust-analyzer/docs/dev/architecture.md
@@ -481,7 +481,7 @@ It is not cheap enough to enable in prod, and this is a bug which should be fixe
 rust-analyzer strives to be as configurable as possible while offering reasonable defaults where no configuration exists yet.
 The rule of thumb is to enable most features by default unless they are buggy or degrade performance too much.
 There will always be features that some people find more annoying than helpful, so giving the users the ability to tweak or disable these is a big part of offering a good user experience.
-Enabling them by default is a matter of discoverability, as many users end up don't know about some features even though they are presented in the manual.
+Enabling them by default is a matter of discoverability, as many users don't know about some features even though they are presented in the manual.
 Mind the code--architecture gap: at the moment, we are using fewer feature flags than we really should.
 
 ### Serialization
@@ -492,8 +492,8 @@ If a type is serializable, then it is a part of some IPC boundary.
 You often don't control the other side of this boundary, so changing serializable types is hard.
 
 For this reason, the types in `ide`, `base_db` and below are not serializable by design.
-If such types need to cross an IPC boundary, then the client of rust-analyzer needs to provide custom, client-specific serialization format.
+If such types need to cross an IPC boundary, then the client of rust-analyzer needs to provide a custom, client-specific serialization format.
 This isolates backwards compatibility and migration concerns to a specific client.
 
-For example, `rust-project.json` is it's own format -- it doesn't include `CrateGraph` as is.
+For example, `rust-project.json` is its own format -- it doesn't include `CrateGraph` as is.
 Instead, it creates a `CrateGraph` by calling appropriate constructing functions.
diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc
index 36794efe427..57f950034cb 100644
--- a/src/tools/rust-analyzer/docs/user/generated_config.adoc
+++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc
@@ -173,7 +173,7 @@ Whether to pass `--no-default-features` to Cargo. Defaults to
 --
 Override the command rust-analyzer uses instead of `cargo check` for
 diagnostics on save. The command is required to output json and
-should therefor include `--message-format=json` or a similar option.
+should therefore include `--message-format=json` or a similar option.
 
 If you're changing this because you're using some tool wrapping
 Cargo, you might also want to change
@@ -190,11 +190,15 @@ cargo check --workspace --message-format=json --all-targets
 ```
 .
 --
-[[rust-analyzer.checkOnSave.target]]rust-analyzer.checkOnSave.target (default: `null`)::
+[[rust-analyzer.checkOnSave.target]]rust-analyzer.checkOnSave.target (default: `[]`)::
 +
 --
-Check for a specific target. Defaults to
-`#rust-analyzer.cargo.target#`.
+Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty.
+
+Can be a single target, e.g. `"x86_64-unknown-linux-gnu"` or a list of targets, e.g.
+`["aarch64-apple-darwin", "x86_64-apple-darwin"]`.
+
+Aliased as `"checkOnSave.targets"`.
 --
 [[rust-analyzer.completion.autoimport.enable]]rust-analyzer.completion.autoimport.enable (default: `true`)::
 +
@@ -450,6 +454,11 @@ to always show them).
 --
 Whether to show inlay type hints for return types of closures.
 --
+[[rust-analyzer.inlayHints.expressionAdjustmentHints.enable]]rust-analyzer.inlayHints.expressionAdjustmentHints.enable (default: `"never"`)::
++
+--
+Whether to show inlay hints for type adjustments.
+--
 [[rust-analyzer.inlayHints.lifetimeElisionHints.enable]]rust-analyzer.inlayHints.lifetimeElisionHints.enable (default: `"never"`)::
 +
 --
@@ -474,7 +483,8 @@ site.
 [[rust-analyzer.inlayHints.reborrowHints.enable]]rust-analyzer.inlayHints.reborrowHints.enable (default: `"never"`)::
 +
 --
-Whether to show inlay type hints for compiler inserted reborrows.
+Whether to show inlay hints for compiler inserted reborrows.
+This setting is deprecated in favor of #rust-analyzer.inlayHints.expressionAdjustmentHints.enable#.
 --
 [[rust-analyzer.inlayHints.renderColons]]rust-analyzer.inlayHints.renderColons (default: `true`)::
 +
diff --git a/src/tools/rust-analyzer/docs/user/manual.adoc b/src/tools/rust-analyzer/docs/user/manual.adoc
index 49500e390a5..1a4c70575b0 100644
--- a/src/tools/rust-analyzer/docs/user/manual.adoc
+++ b/src/tools/rust-analyzer/docs/user/manual.adoc
@@ -367,7 +367,7 @@ if executable('rust-analyzer')
 endif
 ----
 
-There is no dedicated UI for the server configuration, so you would need to send any options as a value of the `initialization_options` field, as described in the <<_configuration,Configuration>> section.
+There is no dedicated UI for the server configuration, so you would need to send any options as a value of the `initialization_options` field, as described in the <<configuration,Configuration>> section.
 Here is an example of how to enable the proc-macro support:
 
 [source,vim]
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index 1a97a9c0893..c4d4e428ea0 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -396,6 +396,11 @@
                     "default": true,
                     "type": "boolean"
                 },
+                "rust-analyzer.diagnostics.previewRustcOutput": {
+                    "markdownDescription": "Whether to show the main part of the rendered rustc output of a diagnostic message.",
+                    "default": false,
+                    "type": "boolean"
+                },
                 "$generated-start": {},
                 "rust-analyzer.assist.emitMustUse": {
                     "markdownDescription": "Whether to insert #[must_use] when generating `as_` methods\nfor enum variants.",
@@ -623,7 +628,7 @@
                     ]
                 },
                 "rust-analyzer.checkOnSave.overrideCommand": {
-                    "markdownDescription": "Override the command rust-analyzer uses instead of `cargo check` for\ndiagnostics on save. The command is required to output json and\nshould therefor include `--message-format=json` or a similar option.\n\nIf you're changing this because you're using some tool wrapping\nCargo, you might also want to change\n`#rust-analyzer.cargo.buildScripts.overrideCommand#`.\n\nIf there are multiple linked projects, this command is invoked for\neach of them, with the working directory being the project root\n(i.e., the folder containing the `Cargo.toml`).\n\nAn example command would be:\n\n```bash\ncargo check --workspace --message-format=json --all-targets\n```\n.",
+                    "markdownDescription": "Override the command rust-analyzer uses instead of `cargo check` for\ndiagnostics on save. The command is required to output json and\nshould therefore include `--message-format=json` or a similar option.\n\nIf you're changing this because you're using some tool wrapping\nCargo, you might also want to change\n`#rust-analyzer.cargo.buildScripts.overrideCommand#`.\n\nIf there are multiple linked projects, this command is invoked for\neach of them, with the working directory being the project root\n(i.e., the folder containing the `Cargo.toml`).\n\nAn example command would be:\n\n```bash\ncargo check --workspace --message-format=json --all-targets\n```\n.",
                     "default": null,
                     "type": [
                         "null",
@@ -634,11 +639,18 @@
                     }
                 },
                 "rust-analyzer.checkOnSave.target": {
-                    "markdownDescription": "Check for a specific target. Defaults to\n`#rust-analyzer.cargo.target#`.",
-                    "default": null,
-                    "type": [
-                        "null",
-                        "string"
+                    "markdownDescription": "Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty.\n\nCan be a single target, e.g. `\"x86_64-unknown-linux-gnu\"` or a list of targets, e.g.\n`[\"aarch64-apple-darwin\", \"x86_64-apple-darwin\"]`.\n\nAliased as `\"checkOnSave.targets\"`.",
+                    "default": [],
+                    "anyOf": [
+                        {
+                            "type": "string"
+                        },
+                        {
+                            "type": "array",
+                            "items": {
+                                "type": "string"
+                            }
+                        }
                     ]
                 },
                 "rust-analyzer.completion.autoimport.enable": {
@@ -935,6 +947,21 @@
                         "Only show type hints for return types of closures with blocks."
                     ]
                 },
+                "rust-analyzer.inlayHints.expressionAdjustmentHints.enable": {
+                    "markdownDescription": "Whether to show inlay hints for type adjustments.",
+                    "default": "never",
+                    "type": "string",
+                    "enum": [
+                        "always",
+                        "never",
+                        "reborrow"
+                    ],
+                    "enumDescriptions": [
+                        "Always show all adjustment hints.",
+                        "Never show adjustment hints.",
+                        "Only show auto borrow and dereference adjustment hints."
+                    ]
+                },
                 "rust-analyzer.inlayHints.lifetimeElisionHints.enable": {
                     "markdownDescription": "Whether to show inlay type hints for elided lifetimes in function signatures.",
                     "default": "never",
@@ -970,7 +997,7 @@
                     "type": "boolean"
                 },
                 "rust-analyzer.inlayHints.reborrowHints.enable": {
-                    "markdownDescription": "Whether to show inlay type hints for compiler inserted reborrows.",
+                    "markdownDescription": "Whether to show inlay hints for compiler inserted reborrows.\nThis setting is deprecated in favor of #rust-analyzer.inlayHints.expressionAdjustmentHints.enable#.",
                     "default": "never",
                     "type": "string",
                     "enum": [
@@ -1276,6 +1303,11 @@
                 "$generated-end": {}
             }
         },
+        "configurationDefaults": {
+            "explorer.fileNesting.patterns": {
+                "Cargo.toml": "Cargo.lock"
+            }
+        },
         "problemPatterns": [
             {
                 "name": "rustc",
diff --git a/src/tools/rust-analyzer/editors/code/src/client.ts b/src/tools/rust-analyzer/editors/code/src/client.ts
index fb667619c86..23e039722ee 100644
--- a/src/tools/rust-analyzer/editors/code/src/client.ts
+++ b/src/tools/rust-analyzer/editors/code/src/client.ts
@@ -4,7 +4,7 @@ import * as ra from "../src/lsp_ext";
 import * as Is from "vscode-languageclient/lib/common/utils/is";
 import { assert } from "./util";
 import { WorkspaceEdit } from "vscode";
-import { substituteVSCodeVariables } from "./config";
+import { Config, substituteVSCodeVariables } from "./config";
 import { randomUUID } from "crypto";
 
 export interface Env {
@@ -66,7 +66,8 @@ export async function createClient(
     traceOutputChannel: vscode.OutputChannel,
     outputChannel: vscode.OutputChannel,
     initializationOptions: vscode.WorkspaceConfiguration,
-    serverOptions: lc.ServerOptions
+    serverOptions: lc.ServerOptions,
+    config: Config
 ): Promise<lc.LanguageClient> {
     const clientOptions: lc.LanguageClientOptions = {
         documentSelector: [{ scheme: "file", language: "rust" }],
@@ -99,6 +100,43 @@ export async function createClient(
                     }
                 },
             },
+            async handleDiagnostics(
+                uri: vscode.Uri,
+                diagnostics: vscode.Diagnostic[],
+                next: lc.HandleDiagnosticsSignature
+            ) {
+                const preview = config.previewRustcOutput;
+                diagnostics.forEach((diag, idx) => {
+                    // Abuse the fact that VSCode leaks the LSP diagnostics data field through the
+                    // Diagnostic class, if they ever break this we are out of luck and have to go
+                    // back to the worst diagnostics experience ever:)
+
+                    // We encode the rendered output of a rustc diagnostic in the rendered field of
+                    // the data payload of the lsp diagnostic. If that field exists, overwrite the
+                    // diagnostic code such that clicking it opens the diagnostic in a readonly
+                    // text editor for easy inspection
+                    const rendered = (diag as unknown as { data?: { rendered?: string } }).data
+                        ?.rendered;
+                    if (rendered) {
+                        if (preview) {
+                            const index = rendered.match(/^(note|help):/m)?.index || 0;
+                            diag.message = rendered
+                                .substring(0, index)
+                                .replace(/^ -->[^\n]+\n/m, "");
+                        }
+                        diag.code = {
+                            target: vscode.Uri.from({
+                                scheme: "rust-analyzer-diagnostics-view",
+                                path: "/diagnostic message",
+                                fragment: uri.toString(),
+                                query: idx.toString(),
+                            }),
+                            value: "Click for full compiler diagnostic",
+                        };
+                    }
+                });
+                return next(uri, diagnostics);
+            },
             async provideHover(
                 document: vscode.TextDocument,
                 position: vscode.Position,
diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts
index 632a7d86faa..d8dbd1df16d 100644
--- a/src/tools/rust-analyzer/editors/code/src/config.ts
+++ b/src/tools/rust-analyzer/editors/code/src/config.ts
@@ -238,6 +238,9 @@ export class Config {
             gotoTypeDef: this.get<boolean>("hover.actions.gotoTypeDef.enable"),
         };
     }
+    get previewRustcOutput() {
+        return this.get<boolean>("diagnostics.previewRustcOutput");
+    }
 }
 
 const VarRegex = new RegExp(/\$\{(.+?)\}/g);
diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts
index 3e366525ee2..d6cee5c8fc6 100644
--- a/src/tools/rust-analyzer/editors/code/src/ctx.ts
+++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts
@@ -179,7 +179,8 @@ export class Ctx {
                 this.traceOutputChannel,
                 this.outputChannel,
                 initializationOptions,
-                serverOptions
+                serverOptions,
+                this.config
             );
             this.pushClientCleanup(
                 this._client.onNotification(ra.serverStatus, (params) =>
diff --git a/src/tools/rust-analyzer/editors/code/src/main.ts b/src/tools/rust-analyzer/editors/code/src/main.ts
index e76b657c1bf..25f1e83d109 100644
--- a/src/tools/rust-analyzer/editors/code/src/main.ts
+++ b/src/tools/rust-analyzer/editors/code/src/main.ts
@@ -48,6 +48,30 @@ async function activateServer(ctx: Ctx): Promise<RustAnalyzerExtensionApi> {
         ctx.pushExtCleanup(activateTaskProvider(ctx.config));
     }
 
+    ctx.pushExtCleanup(
+        vscode.workspace.registerTextDocumentContentProvider(
+            "rust-analyzer-diagnostics-view",
+            new (class implements vscode.TextDocumentContentProvider {
+                async provideTextDocumentContent(uri: vscode.Uri): Promise<string> {
+                    const diags = ctx.client?.diagnostics?.get(
+                        vscode.Uri.parse(uri.fragment, true)
+                    );
+                    if (!diags) {
+                        return "Unable to find original rustc diagnostic";
+                    }
+
+                    const diag = diags[parseInt(uri.query)];
+                    if (!diag) {
+                        return "Unable to find original rustc diagnostic";
+                    }
+                    const rendered = (diag as unknown as { data?: { rendered?: string } }).data
+                        ?.rendered;
+                    return rendered ?? "Unable to find original rustc diagnostic";
+                }
+            })()
+        )
+    );
+
     vscode.workspace.onDidChangeWorkspaceFolders(
         async (_) => ctx.onWorkspaceFolderChanges(),
         null,
diff --git a/src/tools/rust-analyzer/xtask/Cargo.toml b/src/tools/rust-analyzer/xtask/Cargo.toml
index 0be0bf920de..95e27beab5d 100644
--- a/src/tools/rust-analyzer/xtask/Cargo.toml
+++ b/src/tools/rust-analyzer/xtask/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.1.0"
 publish = false
 license = "MIT OR Apache-2.0"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [dependencies]
 anyhow = "1.0.62"
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index d5611082f01..414e767690b 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -660,7 +660,7 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option<ControlFlow<
         ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => {
             Some(ControlFlow::new_for(pat, cond, block, label, expr.span))
         }
-        ast::ExprKind::Loop(ref block, label) => {
+        ast::ExprKind::Loop(ref block, label, _) => {
             Some(ControlFlow::new_loop(block, label, expr.span))
         }
         ast::ExprKind::While(ref cond, ref block, label) => {