about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/builder/tests.rs3
-rw-r--r--src/bootstrap/native.rs4
-rw-r--r--src/bootstrap/test.rs25
-rw-r--r--src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-10/Dockerfile (renamed from src/ci/docker/host-x86_64/x86_64-gnu-llvm-9/Dockerfile)9
-rw-r--r--src/ci/github-actions/ci.yml4
m---------src/doc/book0
m---------src/doc/embedded-book0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/rustc/src/targets/built-in.md2
-rw-r--r--src/doc/rustdoc/src/unstable-features.md42
-rw-r--r--src/doc/unstable-book/src/language-features/doc-notable-trait.md33
-rw-r--r--src/doc/unstable-book/src/language-features/doc-spotlight.md30
-rw-r--r--src/librustdoc/clean/blanket_impl.rs16
-rw-r--r--src/librustdoc/clean/inline.rs22
-rw-r--r--src/librustdoc/clean/mod.rs21
-rw-r--r--src/librustdoc/clean/types.rs58
-rw-r--r--src/librustdoc/clean/utils.rs26
-rw-r--r--src/librustdoc/doctest.rs2
-rw-r--r--src/librustdoc/formats/cache.rs2
-rw-r--r--src/librustdoc/formats/renderer.rs7
-rw-r--r--src/librustdoc/html/format.rs717
-rw-r--r--src/librustdoc/html/markdown.rs2
-rw-r--r--src/librustdoc/html/render/context.rs2
-rw-r--r--src/librustdoc/html/render/mod.rs172
-rw-r--r--src/librustdoc/html/render/print_item.rs129
-rw-r--r--src/librustdoc/html/render/write_shared.rs2
-rw-r--r--src/librustdoc/html/sources.rs8
-rw-r--r--src/librustdoc/html/static/main.js25
-rw-r--r--src/librustdoc/html/static/noscript.css5
-rw-r--r--src/librustdoc/html/static/rustdoc.css27
-rw-r--r--src/librustdoc/html/static/themes/ayu.css5
-rw-r--r--src/librustdoc/html/static/themes/dark.css5
-rw-r--r--src/librustdoc/html/static/themes/light.css5
-rw-r--r--src/librustdoc/json/conversions.rs321
-rw-r--r--src/librustdoc/json/mod.rs16
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs10
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs90
-rw-r--r--src/librustdoc/visit_ast.rs4
m---------src/llvm-project0
-rw-r--r--src/test/assembly/asm/aarch64-modifiers.rs2
-rw-r--r--src/test/assembly/asm/aarch64-types.rs2
-rw-r--r--src/test/assembly/asm/arm-modifiers.rs2
-rw-r--r--src/test/assembly/asm/arm-types.rs2
-rw-r--r--src/test/assembly/asm/hexagon-types.rs2
-rw-r--r--src/test/assembly/asm/mips-types.rs2
-rw-r--r--src/test/assembly/asm/nvptx-types.rs2
-rw-r--r--src/test/assembly/asm/riscv-types.rs2
-rw-r--r--src/test/assembly/asm/wasm-types.rs2
-rw-r--r--src/test/assembly/asm/x86-modifiers.rs2
-rw-r--r--src/test/assembly/asm/x86-types.rs2
-rw-r--r--src/test/codegen/alloc-optimisation.rs2
-rw-r--r--src/test/codegen/binary-search-index-no-bound-check.rs19
-rw-r--r--src/test/codegen/issue-83623-SIMD-PartialEq.rs46
-rw-r--r--src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs1
-rw-r--r--src/test/incremental/hashes/function_interfaces.rs6
-rw-r--r--src/test/incremental/hashes/inherent_impls.rs6
-rw-r--r--src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff2
-rw-r--r--src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff2
-rw-r--r--src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff2
-rw-r--r--src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff2
-rw-r--r--src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff2
-rw-r--r--src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff2
-rw-r--r--src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff2
-rw-r--r--src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff2
-rw-r--r--src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff2
-rw-r--r--src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir4
-rw-r--r--src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff2
-rw-r--r--src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff2
-rw-r--r--src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff2
-rw-r--r--src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff2
-rw-r--r--src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff6
-rw-r--r--src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir2
-rw-r--r--src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir2
-rw-r--r--src/test/run-make-fulldeps/coverage-llvmir/Makefile2
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generics.txt4
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt4
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_inline_crate.txt29
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.conditions/conditions.main.-------.InstrumentCoverage.0.html382
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html170
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-eq.-------.InstrumentCoverage.0.html2
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-ne.-------.InstrumentCoverage.0.html2
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.unused/unused.foo.-------.InstrumentCoverage.0.html10
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.unused/unused.unused_template_func.-------.InstrumentCoverage.0.html10
-rw-r--r--src/test/run-make-fulldeps/coverage/lib/used_inline_crate.rs12
-rw-r--r--src/test/run-make-fulldeps/issue-83045/Makefile33
-rw-r--r--src/test/run-make-fulldeps/issue-83045/a.rs1
-rw-r--r--src/test/run-make-fulldeps/issue-83045/b.rs1
-rw-r--r--src/test/run-make-fulldeps/issue-83045/c.rs1
-rw-r--r--src/test/run-make/incr-prev-body-beyond-eof/Makefile10
-rw-r--r--src/test/run-make/issue-36710/Makefile15
-rw-r--r--src/test/run-make/issue-83112-incr-test-moved-file/Makefile8
-rw-r--r--src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml21
-rw-r--r--src/test/rustdoc-json/reexport/in_root_and_mod.rs15
-rw-r--r--src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs20
-rw-r--r--src/test/rustdoc-json/reexport/rename_private.rs14
-rw-r--r--src/test/rustdoc-ui/check-doc-alias-attr.stderr4
-rw-r--r--src/test/rustdoc-ui/doc-spotlight.fixed10
-rw-r--r--src/test/rustdoc-ui/doc-spotlight.rs10
-rw-r--r--src/test/rustdoc-ui/doc-spotlight.stderr14
-rw-r--r--src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs13
-rw-r--r--src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr45
-rw-r--r--src/test/rustdoc/doc-notable_trait.rs (renamed from src/test/rustdoc/doc-spotlight.rs)10
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs2
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-for-crate.rs2
-rw-r--r--src/test/ui/asm/const.rs2
-rw-r--r--src/test/ui/asm/inline-syntax.arm.stderr74
-rw-r--r--src/test/ui/asm/inline-syntax.rs25
-rw-r--r--src/test/ui/asm/inline-syntax.x86_64.stderr50
-rw-r--r--src/test/ui/asm/srcloc.rs4
-rw-r--r--src/test/ui/asm/sym.rs4
-rw-r--r--src/test/ui/associated-type-bounds/hrtb.rs65
-rw-r--r--src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr8
-rw-r--r--src/test/ui/associated-types/issue-44153.stderr2
-rw-r--r--src/test/ui/async-await/issues/issue-64964.rs2
-rw-r--r--src/test/ui/async-await/pin-needed-to-poll.rs47
-rw-r--r--src/test/ui/async-await/pin-needed-to-poll.stderr22
-rw-r--r--src/test/ui/binding/issue-53114-safety-checks.rs8
-rw-r--r--src/test/ui/binding/issue-53114-safety-checks.stderr68
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr8
-rw-r--r--src/test/ui/command/command-setgroups.rs1
-rw-r--r--src/test/ui/const-generics/defaults/complex-unord-param.rs18
-rw-r--r--src/test/ui/const-generics/defaults/default-annotation.rs4
-rw-r--r--src/test/ui/const-generics/defaults/mismatch.rs24
-rw-r--r--src/test/ui/const-generics/defaults/mismatch.stderr50
-rw-r--r--src/test/ui/const-generics/defaults/needs-feature.rs2
-rw-r--r--src/test/ui/const-generics/defaults/repr-c-issue-82792.rs14
-rw-r--r--src/test/ui/const-generics/defaults/simple-defaults.rs6
-rw-r--r--src/test/ui/const-generics/issues/issue-56445-1.full.stderr (renamed from src/test/ui/const-generics/issues/issue-56445.full.stderr)4
-rw-r--r--src/test/ui/const-generics/issues/issue-56445-1.min.stderr (renamed from src/test/ui/const-generics/issues/issue-56445.min.stderr)2
-rw-r--r--src/test/ui/const-generics/issues/issue-56445-1.rs (renamed from src/test/ui/const-generics/issues/issue-56445.rs)0
-rw-r--r--src/test/ui/const-generics/issues/issue-56445-2.rs11
-rw-r--r--src/test/ui/const-generics/issues/issue-56445-2.stderr14
-rw-r--r--src/test/ui/const-generics/issues/issue-56445-3.rs12
-rw-r--r--src/test/ui/const-generics/issues/issue-56445-3.stderr8
-rw-r--r--src/test/ui/const-generics/issues/issue-69654-run-pass.rs2
-rw-r--r--src/test/ui/const-generics/issues/issue-69654-run-pass.stderr15
-rw-r--r--src/test/ui/const-generics/issues/issue-69654.rs1
-rw-r--r--src/test/ui/const-generics/issues/issue-69654.stderr17
-rw-r--r--src/test/ui/const-generics/occurs-check/unused-substs-1.rs3
-rw-r--r--src/test/ui/const-generics/occurs-check/unused-substs-1.stderr17
-rw-r--r--src/test/ui/const-generics/occurs-check/unused-substs-2.rs3
-rw-r--r--src/test/ui/const-generics/occurs-check/unused-substs-2.stderr9
-rw-r--r--src/test/ui/const-generics/occurs-check/unused-substs-3.rs3
-rw-r--r--src/test/ui/const-generics/occurs-check/unused-substs-3.stderr12
-rw-r--r--src/test/ui/const-generics/occurs-check/unused-substs-4.rs3
-rw-r--r--src/test/ui/const-generics/occurs-check/unused-substs-4.stderr9
-rw-r--r--src/test/ui/consts/const-eval/conditional_array_execution.rs2
-rw-r--r--src/test/ui/consts/const-eval/const-eval-query-stack.stderr2
-rw-r--r--src/test/ui/consts/const-eval/issue-44578.rs2
-rw-r--r--src/test/ui/copy-a-resource.stderr8
-rw-r--r--src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs2
-rw-r--r--src/test/ui/dep-graph/dep-graph-caller-callee.rs2
-rw-r--r--src/test/ui/dep-graph/dep-graph-struct-signature.rs2
-rw-r--r--src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs2
-rw-r--r--src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs2
-rw-r--r--src/test/ui/dep-graph/dep-graph-trait-impl.rs2
-rw-r--r--src/test/ui/dep-graph/dep-graph-type-alias.rs2
-rw-r--r--src/test/ui/dep-graph/dep-graph-variance-alias.rs2
-rw-r--r--src/test/ui/derives/derive-assoc-type-not-impl.stderr8
-rw-r--r--src/test/ui/derives/deriving-with-repr-packed.rs2
-rw-r--r--src/test/ui/derives/deriving-with-repr-packed.stderr12
-rw-r--r--src/test/ui/error-codes/E0106.stderr22
-rw-r--r--src/test/ui/feature-gates/feature-gate-doc_notable_trait.rs4
-rw-r--r--src/test/ui/feature-gates/feature-gate-doc_notable_trait.stderr12
-rw-r--r--src/test/ui/feature-gates/feature-gate-doc_spotlight.rs4
-rw-r--r--src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr12
-rw-r--r--src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr168
-rw-r--r--src/test/ui/generator/type-mismatch-signature-deduction.stderr6
-rw-r--r--src/test/ui/generic-associated-types/shadowing.stderr16
-rw-r--r--src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr22
-rw-r--r--src/test/ui/generics/wrong-number-of-args.stderr66
-rw-r--r--src/test/ui/hrtb/complex.rs28
-rw-r--r--src/test/ui/impl-trait/bound-normalization-fail.stderr12
-rw-r--r--src/test/ui/impl-trait/equality2.stderr6
-rw-r--r--src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr8
-rw-r--r--src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr8
-rw-r--r--src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs20
-rw-r--r--src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr11
-rw-r--r--src/test/ui/inference/issue-83606.rs10
-rw-r--r--src/test/ui/inference/issue-83606.stderr11
-rw-r--r--src/test/ui/issue-83639.rs6
-rw-r--r--src/test/ui/issue-83639.stderr8
-rw-r--r--src/test/ui/issues/issue-27060-rpass.rs8
-rw-r--r--src/test/ui/issues/issue-27060.rs14
-rw-r--r--src/test/ui/issues/issue-27060.stderr40
-rw-r--r--src/test/ui/issues/issue-2823.stderr8
-rw-r--r--src/test/ui/issues/issue-33941.stderr12
-rw-r--r--src/test/ui/issues/issue-39970.stderr2
-rw-r--r--src/test/ui/issues/issue-69725.stderr8
-rw-r--r--src/test/ui/iterators/array-of-ranges.stderr24
-rw-r--r--src/test/ui/iterators/array.stderr12
-rw-r--r--src/test/ui/iterators/ranges.stderr6
-rw-r--r--src/test/ui/iterators/string.stderr2
-rw-r--r--src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr20
-rw-r--r--src/test/ui/lint/unaligned_references.rs21
-rw-r--r--src/test/ui/lint/unaligned_references.stderr36
-rw-r--r--src/test/ui/lint/unaligned_references_external_macro.rs3
-rw-r--r--src/test/ui/lint/unaligned_references_external_macro.stderr8
-rw-r--r--src/test/ui/macros/issue-83340.rs8
-rw-r--r--src/test/ui/macros/issue-83340.stderr8
-rw-r--r--src/test/ui/macros/issue-83344.rs6
-rw-r--r--src/test/ui/macros/issue-83344.stderr8
-rw-r--r--src/test/ui/macros/macro-or-patterns-back-compat.fixed26
-rw-r--r--src/test/ui/macros/macro-or-patterns-back-compat.rs26
-rw-r--r--src/test/ui/macros/macro-or-patterns-back-compat.stderr32
-rw-r--r--src/test/ui/mir/issue-83499-input-output-iteration-ice.rs10
-rw-r--r--src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr21
-rw-r--r--src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs2
-rw-r--r--src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr18
-rw-r--r--src/test/ui/nll/closure-requirements/escape-argument-callee.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/escape-argument.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr4
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr2
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr4
-rw-r--r--src/test/ui/non-copyable-void.stderr8
-rw-r--r--src/test/ui/noncopyable-class.stderr8
-rw-r--r--src/test/ui/packed/packed-struct-address-of-element.rs2
-rw-r--r--src/test/ui/packed/packed-struct-borrow-element-64bit.rs17
-rw-r--r--src/test/ui/packed/packed-struct-borrow-element-64bit.stderr13
-rw-r--r--src/test/ui/packed/packed-struct-borrow-element.rs10
-rw-r--r--src/test/ui/packed/packed-struct-borrow-element.stderr23
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-75801.rs13
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-79825.rs14
-rw-r--r--src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs9
-rw-r--r--src/test/ui/proc-macro/generate-mod.stderr12
-rw-r--r--src/test/ui/proc-macro/inner-attrs.rs21
-rw-r--r--src/test/ui/proc-macro/inner-attrs.stderr32
-rw-r--r--src/test/ui/proc-macro/inner-attrs.stdout302
-rw-r--r--src/test/ui/proc-macro/issue-75801.rs19
-rw-r--r--src/test/ui/proc-macro/issue-75801.stderr12
-rw-r--r--src/test/ui/proc-macro/issue-79825.rs10
-rw-r--r--src/test/ui/proc-macro/issue-81555.rs15
-rw-r--r--src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs10
-rw-r--r--src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr8
-rw-r--r--src/test/ui/proc-macro/nested-macro-rules.rs10
-rw-r--r--src/test/ui/proc-macro/nested-macro-rules.stdout52
-rw-r--r--src/test/ui/regions/regions-name-undeclared.stderr40
-rw-r--r--src/test/ui/resolve/issue-82865.rs13
-rw-r--r--src/test/ui/resolve/issue-82865.stderr21
-rw-r--r--src/test/ui/rustdoc/check-doc-alias-attr.stderr4
-rw-r--r--src/test/ui/self/point-at-arbitrary-self-type-method.stderr5
-rw-r--r--src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr5
-rw-r--r--src/test/ui/simd/simd-intrinsic-generic-reduction.rs1
-rw-r--r--src/test/ui/specialization/issue-68830-spurious-diagnostics.rs23
-rw-r--r--src/test/ui/specialization/issue-68830-spurious-diagnostics.stderr9
-rw-r--r--src/test/ui/specialization/min_specialization/repeated_projection_type.stderr2
-rw-r--r--src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr2
-rw-r--r--src/test/ui/suggestions/into-str.stderr1
-rw-r--r--src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr92
-rw-r--r--src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs7
-rw-r--r--src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr107
-rw-r--r--src/test/ui/suggestions/missing-lifetime-specifier.stderr48
-rw-r--r--src/test/ui/suggestions/path-display.stderr4
-rw-r--r--src/test/ui/symbol-names/basic.legacy.stderr4
-rw-r--r--src/test/ui/symbol-names/issue-60925.legacy.stderr4
-rw-r--r--src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-63279.full_tait.stderr6
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-63279.min_tait.stderr6
-rw-r--r--src/test/ui/union/union-derive-clone.stderr8
-rw-r--r--src/test/ui/unique-object-noncopyable.stderr8
-rw-r--r--src/test/ui/unique-pinned-nocopy.stderr8
-rw-r--r--src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs67
-rw-r--r--src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr60
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/CHANGELOG.md1
-rw-r--r--src/tools/clippy/CONTRIBUTING.md36
-rw-r--r--src/tools/clippy/Cargo.toml4
-rw-r--r--src/tools/clippy/clippy_dev/src/fmt.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/ide_setup.rs (renamed from src/tools/clippy/clippy_dev/src/ra_setup.rs)2
-rw-r--r--src/tools/clippy/clippy_dev/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/main.rs8
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml5
-rw-r--r--src/tools/clippy/clippy_lints/src/approx_const.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/arithmetic.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/as_conversions.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/asm_syntax.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/assertions_on_constants.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/assign_ops.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/async_yields_async.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/atomic_ordering.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/await_holding_invalid.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/bit_mask.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/blacklisted_name.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/bytecount.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_ref_to_mut.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/mod.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/checked_conversions.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/cognitive_complexity.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/collapsible_if.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/collapsible_match.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/comparison_chain.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/copies.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/copy_iterator.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/create_dir.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/dbg_macro.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/default.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs322
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_method.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/doc.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/double_comparison.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/double_parens.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/drop_forget_ref.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/duration_subsec.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/else_if_without_else.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_enum.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_clike.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_variants.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/eq_op.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/erasing_op.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/eval_order_dependence.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/excessive_bools.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/exhaustive_items.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/exit.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/explicit_write.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/fallible_impl_from.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/float_literal.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/format.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/formatting.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/from_over_into.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/from_str_radix_10.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/functions.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/get_last_with_len.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/identity_op.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/if_let_mutex.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/if_let_some_result.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/if_not_else.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs117
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_return.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/indexing_slicing.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/infinite_iter.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/inherent_impl.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/inherent_to_string.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/int_plus_one.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/integer_division.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/items_after_statements.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_const_arrays.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_enum_variant.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/large_stack_arrays.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/let_if_seq.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/let_underscore.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/literal_representation.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/empty_loop.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_collect.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/same_item_push.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/utils.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_use.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/main_recursion.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_map.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_ok_or.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/map_clone.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/map_err_ignore.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/map_identity.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/map_unit_fn.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/match_on_vec_items.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches.rs286
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_discriminant.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_forget.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_replace.rs42
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs54
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs44
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_last_cmp.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_next_cmp.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/expect_used.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_flat_map.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map_flat_map.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map_map.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_next.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/inspect_for_each.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs51
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_count.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_nth.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_flatten.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs386
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/ok_expect.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/search_is_some.rs117
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/single_char_add_str.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs40
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/skip_while_next.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs62
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs46
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/uninit_assumed_init.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/useless_asref.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/utils.rs77
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs91
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/zst_offset.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/minmax.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_key.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_mut.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_reference.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/mutex_atomic.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_bool.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrow.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_continue.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_question_mark.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_update.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/neg_multiply.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/new_without_default.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/no_effect.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/non_expressive_names.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/open_options.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/option_env_unwrap.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/panic_unimplemented.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/precedence.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr_eq.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_clone.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_closure_call.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_else.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_field_names.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_slicing.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/ref_option_ref.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/reference.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/regex.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/repeat_once.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/self_assignment.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/serde_api.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/shadow.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/single_component_path_imports.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/stable_sort_primitive.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs44
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/swap.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/temporary_assignment.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/to_digit_is_some.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/to_string_in_display.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/trait_bounds.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/utils.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmuting_null.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/try_err.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/types/borrowed_box.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/types/box_vec.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/types/linked_list.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs415
-rw-r--r--src/tools/clippy/clippy_lints/src/types/option_option.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/types/rc_buffer.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/types/utils.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/types/vec_box.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unicode.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/mod.rs107
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs207
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs56
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/utils.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/unnamed_address.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs42
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_io_amount.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_self.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_unit.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap_in_result.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/inspector.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/vec.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/vec_init_then_push.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/verbose_file_reads.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/wildcard_imports.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs315
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_div_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs5
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml4
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs13
-rw-r--r--src/tools/clippy/clippy_utils/src/diagnostics.rs18
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs27
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs886
-rw-r--r--src/tools/clippy/clippy_utils/src/numeric_literal.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/ptr.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/source.rs420
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs305
-rw-r--r--src/tools/clippy/clippy_utils/src/usage.rs4
-rw-r--r--src/tools/clippy/doc/basics.md4
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs5
-rw-r--r--src/tools/clippy/tests/ui/def_id_nocore.stderr3
-rw-r--r--src/tools/clippy/tests/ui/dereference.stderr70
-rw-r--r--src/tools/clippy/tests/ui/explicit_deref_methods.fixed (renamed from src/tools/clippy/tests/ui/dereference.fixed)10
-rw-r--r--src/tools/clippy/tests/ui/explicit_deref_methods.rs (renamed from src/tools/clippy/tests/ui/dereference.rs)2
-rw-r--r--src/tools/clippy/tests/ui/explicit_deref_methods.stderr76
-rw-r--r--src/tools/clippy/tests/ui/field_reassign_with_default.rs18
-rw-r--r--src/tools/clippy/tests/ui/field_reassign_with_default.stderr26
-rw-r--r--src/tools/clippy/tests/ui/if_then_some_else_none.rs104
-rw-r--r--src/tools/clippy/tests/ui/if_then_some_else_none.stderr61
-rw-r--r--src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr4
-rw-r--r--src/tools/clippy/tests/ui/manual_flatten.rs22
-rw-r--r--src/tools/clippy/tests/ui/manual_flatten.stderr85
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option.fixed5
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option.rs9
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option.stderr21
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or.fixed15
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or.rs15
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding2.fixed37
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding2.rs37
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding2.stderr34
-rw-r--r--src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed52
-rw-r--r--src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs52
-rw-r--r--src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr44
-rw-r--r--src/tools/clippy/tests/ui/mem_replace.fixed29
-rw-r--r--src/tools/clippy/tests/ui/mem_replace.rs29
-rw-r--r--src/tools/clippy/tests/ui/mem_replace.stderr78
-rw-r--r--src/tools/clippy/tests/ui/needless_question_mark.fixed25
-rw-r--r--src/tools/clippy/tests/ui/needless_question_mark.rs25
-rw-r--r--src/tools/clippy/tests/ui/needless_question_mark.stderr13
-rw-r--r--src/tools/clippy/tests/ui/new_ret_no_self.rs10
-rw-r--r--src/tools/clippy/tests/ui/new_without_default.rs15
-rw-r--r--src/tools/clippy/tests/ui/new_without_default.stderr38
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.fixed17
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.rs17
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.stderr20
-rw-r--r--src/tools/clippy/tests/ui/print.stderr12
-rw-r--r--src/tools/clippy/tests/ui/print_literal.stderr70
-rw-r--r--src/tools/clippy/tests/ui/search_is_some.rs37
-rw-r--r--src/tools/clippy/tests/ui/search_is_some.stderr44
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable.fixed35
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable.rs35
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable.stderr92
-rw-r--r--src/tools/clippy/tests/ui/string_lit_as_bytes.fixed6
-rw-r--r--src/tools/clippy/tests/ui/string_lit_as_bytes.rs6
-rw-r--r--src/tools/clippy/tests/ui/string_lit_as_bytes.stderr18
-rw-r--r--src/tools/clippy/tests/ui/suspicious_map.rs27
-rw-r--r--src/tools/clippy/tests/ui/suspicious_map.stderr10
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_cast.stderr10
-rw-r--r--src/tools/clippy/tests/ui/upper_case_acronyms.rs4
-rw-r--r--src/tools/clippy/tests/ui/use_self.fixed6
-rw-r--r--src/tools/clippy/tests/ui/use_self.rs6
-rw-r--r--src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed2
-rw-r--r--src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr12
-rw-r--r--src/tools/clippy/tests/ui/write_literal.stderr70
-rw-r--r--src/tools/clippy/tests/ui/write_literal_2.rs27
-rw-r--r--src/tools/clippy/tests/ui/write_literal_2.stderr107
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_convention.rs32
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_convention.stderr111
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs30
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr19
-rw-r--r--src/tools/compiletest/src/header.rs6
-rw-r--r--src/tools/compiletest/src/tests.rs4
-rw-r--r--src/tools/jsondocck/Cargo.toml1
-rw-r--r--src/tools/jsondocck/src/cache.rs10
-rw-r--r--src/tools/jsondocck/src/main.rs20
m---------src/tools/miri16
m---------src/tools/rust-analyzer37
-rw-r--r--src/tools/tidy/src/deps.rs2
701 files changed, 9220 insertions, 5177 deletions
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index 885fcfff030..a881512e988 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -585,8 +585,11 @@ mod dist {
             rustfix_coverage: false,
             pass: None,
         };
+        // Make sure rustfmt binary not being found isn't an error.
+        config.channel = "beta".to_string();
         let build = Build::new(config);
         let mut builder = Builder::new(&build);
+
         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
         let a = TargetSelection::from_user("A");
 
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index fb5127bac54..305ff071dbb 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -347,11 +347,11 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
     let version = output(cmd.arg("--version"));
     let mut parts = version.split('.').take(2).filter_map(|s| s.parse::<u32>().ok());
     if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) {
-        if major >= 9 {
+        if major >= 10 {
             return;
         }
     }
-    panic!("\n\nbad LLVM version: {}, need >=9.0\n\n", version)
+    panic!("\n\nbad LLVM version: {}, need >=10.0\n\n", version)
 }
 
 fn configure_cmake(
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 86d940cd733..adb0a372c64 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -108,6 +108,19 @@ impl Step for Linkcheck {
     /// documentation to ensure we don't have a bunch of dead ones.
     fn run(self, builder: &Builder<'_>) {
         let host = self.host;
+        let hosts = &builder.hosts;
+        let targets = &builder.targets;
+
+        // if we have different hosts and targets, some things may be built for
+        // the host (e.g. rustc) and others for the target (e.g. std). The
+        // documentation built for each will contain broken links to
+        // docs built for the other platform (e.g. rustc linking to cargo)
+        if (hosts != targets) && !hosts.is_empty() && !targets.is_empty() {
+            panic!(
+                "Linkcheck currently does not support builds with different hosts and targets.
+You can skip linkcheck with --exclude src/tools/linkchecker"
+            );
+        }
 
         builder.info(&format!("Linkcheck ({})", host));
 
@@ -122,7 +135,8 @@ impl Step for Linkcheck {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        run.path("src/tools/linkchecker").default_condition(builder.config.docs)
+        let run = run.path("src/tools/linkchecker");
+        run.default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -452,7 +466,14 @@ impl Step for Miri {
 
             cargo.add_rustc_lib_path(builder, compiler);
 
-            if !try_run(builder, &mut cargo.into()) {
+            let mut cargo = Command::from(cargo);
+            if !try_run(builder, &mut cargo) {
+                return;
+            }
+
+            // # Run `cargo test` with `-Zmir-opt-level=4`.
+            cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4");
+            if !try_run(builder, &mut cargo) {
                 return;
             }
 
diff --git a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile b/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile
index f3f52ed61d1..4377608700b 100644
--- a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile
@@ -98,6 +98,6 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS --qemu-riscv64-rootfs=/tmp/rootfs
-ENV SCRIPT python3 ../x.py --stage 2 test --target riscv64gc-unknown-linux-gnu
+ENV SCRIPT python3 ../x.py --stage 2 test --host='' --target riscv64gc-unknown-linux-gnu
 
 ENV NO_CHANGE_USER=1
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-9/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-10/Dockerfile
index 38eac6588b0..c34198708c4 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-9/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-10/Dockerfile
@@ -13,8 +13,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   cmake \
   sudo \
   gdb \
-  llvm-9-tools \
-  llvm-9-dev \
+  llvm-10-tools \
+  llvm-10-dev \
   libedit-dev \
   libssl-dev \
   pkg-config \
@@ -28,7 +28,7 @@ RUN sh /scripts/sccache.sh
 # using llvm-link-shared due to libffi issues -- see #34486
 ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
-      --llvm-root=/usr/lib/llvm-9 \
+      --llvm-root=/usr/lib/llvm-10 \
       --enable-llvm-link-shared \
       --set rust.thin-lto-import-instr-limit=10
 
@@ -46,6 +46,7 @@ ENV SCRIPT python2.7 ../x.py --stage 2 test --exclude src/tools/tidy && \
            # This is intended to make sure that both `--pass=check` continues to
            # work.
            #
-           python2.7 ../x.py --stage 2 test src/test/ui --pass=check --target=i686-unknown-linux-gnu && \
+           python2.7 ../x.py --stage 2 test src/test/ui --pass=check \
+                             --host='' --target=i686-unknown-linux-gnu && \
            # Run tidy at the very end, after all the other tests.
            python2.7 ../x.py --stage 2 test src/tools/tidy
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index c0a84444a59..a59a90b86bc 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -280,7 +280,7 @@ jobs:
           - name: mingw-check
             <<: *job-linux-xl
 
-          - name: x86_64-gnu-llvm-9
+          - name: x86_64-gnu-llvm-10
             <<: *job-linux-xl
 
           - name: x86_64-gnu-tools
@@ -412,7 +412,7 @@ jobs:
           - name: x86_64-gnu-distcheck
             <<: *job-linux-xl
 
-          - name: x86_64-gnu-llvm-9
+          - name: x86_64-gnu-llvm-10
             env:
               RUST_BACKTRACE: 1
             <<: *job-linux-xl
diff --git a/src/doc/book b/src/doc/book
-Subproject fc2f690fc16592abbead2360cfc0a42f5df7805
+Subproject b54090a99ec7c4b46a5203a9c927fdbc311bb1f
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject f61685755fad7d3b88b4645adfbf461d500563a
+Subproject d3f2ace94d51610cf3e3c265705bb8416d37f8e
diff --git a/src/doc/reference b/src/doc/reference
-Subproject d10a0af8dca25d9d548ca6a369fd66ad06acb3c
+Subproject fd97729e2d82f8b08d68a31c9bfdf0c37a7fd54
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject eead22c6c030fa4f3a167d1798658c341199e2a
+Subproject 29d91f591c90dd18fdca6d23f1a9caf9c139d0d
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 67ebd4b55dba44edfc351621cef6e5e758169c5
+Subproject 0687daac28939c476df51778f5a1d1aff1a3fdd
diff --git a/src/doc/rustc/src/targets/built-in.md b/src/doc/rustc/src/targets/built-in.md
index c33b506cdae..344048ee4a1 100644
--- a/src/doc/rustc/src/targets/built-in.md
+++ b/src/doc/rustc/src/targets/built-in.md
@@ -12,4 +12,4 @@ library built by the official Rust distributions. Most targets will need a
 system linker, and possibly other things.
 
 [rustup]: https://github.com/rust-lang/rustup
-[rustup-cross]: https://github.com/rust-lang/rustup#cross-compilation
+[rustup-cross]: https://rust-lang.github.io/rustup/cross-compilation.html
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 7d1845dc957..28b81a40265 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -88,26 +88,28 @@ Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg].
 [unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html
 [issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781
 
-### Adding your trait to the "Important Traits" dialog
-
-Rustdoc keeps a list of a few traits that are believed to be "fundamental" to a given type when
-implemented on it. These traits are intended to be the primary interface for their types, and are
-often the only thing available to be documented on their types. For this reason, Rustdoc will track
-when a given type implements one of these traits and call special attention to it when a function
-returns one of these types. This is the "Important Traits" dialog, visible as a circle-i button next
-to the function, which, when clicked, shows the dialog.
-
-In the standard library, the traits that qualify for inclusion are `Iterator`, `io::Read`, and
-`io::Write`. However, rather than being implemented as a hard-coded list, these traits have a
-special marker attribute on them: `#[doc(spotlight)]`. This means that you could apply this
-attribute to your own trait to include it in the "Important Traits" dialog in documentation.
-
-The `#[doc(spotlight)]` attribute currently requires the `#![feature(doc_spotlight)]` feature gate.
-For more information, see [its chapter in the Unstable Book][unstable-spotlight] and [its tracking
-issue][issue-spotlight].
-
-[unstable-spotlight]: ../unstable-book/language-features/doc-spotlight.html
-[issue-spotlight]: https://github.com/rust-lang/rust/issues/45040
+### Adding your trait to the "Notable traits" dialog
+
+Rustdoc keeps a list of a few traits that are believed to be "fundamental" to
+types that implement them. These traits are intended to be the primary interface
+for their implementers, and are often most of the API available to be documented
+on their types. For this reason, Rustdoc will track when a given type implements
+one of these traits and call special attention to it when a function returns one
+of these types. This is the "Notable traits" dialog, accessible as a circled `i`
+button next to the function, which, when clicked, shows the dialog.
+
+In the standard library, some of the traits that are part of this list are
+`Iterator`, `Future`, `io::Read`, and `io::Write`. However, rather than being
+implemented as a hard-coded list, these traits have a special marker attribute
+on them: `#[doc(notable_trait)]`. This means that you can apply this attribute
+to your own trait to include it in the "Notable traits" dialog in documentation.
+
+The `#[doc(notable_trait)]` attribute currently requires the `#![feature(doc_notable_trait)]`
+feature gate. For more information, see [its chapter in the Unstable Book][unstable-notable_trait]
+and [its tracking issue][issue-notable_trait].
+
+[unstable-notable_trait]: ../unstable-book/language-features/doc-notable-trait.html
+[issue-notable_trait]: https://github.com/rust-lang/rust/issues/45040
 
 ### Exclude certain dependencies from documentation
 
diff --git a/src/doc/unstable-book/src/language-features/doc-notable-trait.md b/src/doc/unstable-book/src/language-features/doc-notable-trait.md
new file mode 100644
index 00000000000..dc402ed4253
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/doc-notable-trait.md
@@ -0,0 +1,33 @@
+# `doc_notable_trait`
+
+The tracking issue for this feature is: [#45040]
+
+The `doc_notable_trait` feature allows the use of the `#[doc(notable_trait)]`
+attribute, which will display the trait in a "Notable traits" dialog for
+functions returning types that implement the trait. For example, this attribute
+is applied to the `Iterator`, `Future`, `io::Read`, and `io::Write` traits in
+the standard library.
+
+You can do this on your own traits like so:
+
+```
+#![feature(doc_notable_trait)]
+
+#[doc(notable_trait)]
+pub trait MyTrait {}
+
+pub struct MyStruct;
+impl MyTrait for MyStruct {}
+
+/// The docs for this function will have a button that displays a dialog about
+/// `MyStruct` implementing `MyTrait`.
+pub fn my_fn() -> MyStruct { MyStruct }
+```
+
+This feature was originally implemented in PR [#45039].
+
+See also its documentation in [the rustdoc book][rustdoc-book-notable_trait].
+
+[#45040]: https://github.com/rust-lang/rust/issues/45040
+[#45039]: https://github.com/rust-lang/rust/pull/45039
+[rustdoc-book-notable_trait]: ../../rustdoc/unstable-features.html#adding-your-trait-to-the-notable-traits-dialog
diff --git a/src/doc/unstable-book/src/language-features/doc-spotlight.md b/src/doc/unstable-book/src/language-features/doc-spotlight.md
deleted file mode 100644
index 75eff163318..00000000000
--- a/src/doc/unstable-book/src/language-features/doc-spotlight.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# `doc_spotlight`
-
-The tracking issue for this feature is: [#45040]
-
-The `doc_spotlight` feature allows the use of the `spotlight` parameter to the `#[doc]` attribute,
-to "spotlight" a specific trait on the return values of functions. Adding a `#[doc(spotlight)]`
-attribute to a trait definition will make rustdoc print extra information for functions which return
-a type that implements that trait. For example, this attribute is applied to the `Iterator`,
-`io::Read`, `io::Write`, and `Future` traits in the standard library.
-
-You can do this on your own traits, like this:
-
-```
-#![feature(doc_spotlight)]
-
-#[doc(spotlight)]
-pub trait MyTrait {}
-
-pub struct MyStruct;
-impl MyTrait for MyStruct {}
-
-/// The docs for this function will have an extra line about `MyStruct` implementing `MyTrait`,
-/// without having to write that yourself!
-pub fn my_fn() -> MyStruct { MyStruct }
-```
-
-This feature was originally implemented in PR [#45039].
-
-[#45040]: https://github.com/rust-lang/rust/issues/45040
-[#45039]: https://github.com/rust-lang/rust/pull/45039
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 6e7164457ce..f7e08d10401 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -26,18 +26,16 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
             {
                 continue;
             }
-            self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| {
+            // NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls
+            let trait_impls = self.cx.tcx.trait_impls_of(trait_def_id);
+            for &impl_def_id in trait_impls.blanket_impls() {
                 debug!(
                     "get_blanket_impls: Considering impl for trait '{:?}' {:?}",
                     trait_def_id, impl_def_id
                 );
                 let trait_ref = self.cx.tcx.impl_trait_ref(impl_def_id).unwrap();
-                let may_apply = self.cx.tcx.infer_ctxt().enter(|infcx| {
-                    match trait_ref.self_ty().kind() {
-                        ty::Param(_) => {}
-                        _ => return false,
-                    }
-
+                let is_param = matches!(trait_ref.self_ty().kind(), ty::Param(_));
+                let may_apply = is_param && self.cx.tcx.infer_ctxt().enter(|infcx| {
                     let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id);
                     let ty = ty.subst(infcx.tcx, substs);
                     let param_env = param_env.subst(infcx.tcx, substs);
@@ -90,7 +88,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                     may_apply, trait_ref, ty
                 );
                 if !may_apply {
-                    return;
+                    continue;
                 }
 
                 self.cx.generated_synthetics.insert((ty, trait_def_id));
@@ -131,7 +129,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                         blanket_impl: Some(trait_ref.self_ty().clean(self.cx)),
                     }),
                 });
-            });
+            }
         }
         impls
     }
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 0d32c14c3be..1e9a7d1b4b9 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -9,7 +9,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc_hir::Mutability;
 use rustc_metadata::creader::LoadedMacro;
-use rustc_middle::ty;
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_mir::const_eval::is_min_const_fn;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -490,23 +490,19 @@ fn build_module(
     clean::Module { items, is_crate: false }
 }
 
-crate fn print_inlined_const(cx: &DocContext<'_>, did: DefId) -> String {
+crate fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
     if let Some(did) = did.as_local() {
-        let hir_id = cx.tcx.hir().local_def_id_to_hir_id(did);
-        rustc_hir_pretty::id_to_string(&cx.tcx.hir(), hir_id)
+        let hir_id = tcx.hir().local_def_id_to_hir_id(did);
+        rustc_hir_pretty::id_to_string(&tcx.hir(), hir_id)
     } else {
-        cx.tcx.rendered_const(did)
+        tcx.rendered_const(did)
     }
 }
 
-fn build_const(cx: &mut DocContext<'_>, did: DefId) -> clean::Constant {
+fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
     clean::Constant {
-        type_: cx.tcx.type_of(did).clean(cx),
-        expr: print_inlined_const(cx, did),
-        value: clean::utils::print_evaluated_const(cx, did),
-        is_literal: did.as_local().map_or(false, |did| {
-            clean::utils::is_literal_expr(cx, cx.tcx.hir().local_def_id_to_hir_id(did))
-        }),
+        type_: cx.tcx.type_of(def_id).clean(cx),
+        kind: clean::ConstantKind::Extern { def_id },
     }
 }
 
@@ -628,7 +624,7 @@ crate fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) {
 
     let trait_ = clean::TraitWithExtraInfo {
         trait_,
-        is_spotlight: clean::utils::has_doc_flag(cx.tcx.get_attrs(did), sym::spotlight),
+        is_spotlight: clean::utils::has_doc_flag(cx.tcx.get_attrs(did), sym::notable_trait),
     };
     cx.external_traits.borrow_mut().insert(did, trait_);
     cx.active_extern_traits.remove(&did);
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 84210276d35..217e899001e 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -129,7 +129,6 @@ impl Clean<ExternalCrate> for CrateNum {
             tcx.hir()
                 .krate()
                 .item
-                .module
                 .item_ids
                 .iter()
                 .filter_map(|&id| {
@@ -174,7 +173,6 @@ impl Clean<ExternalCrate> for CrateNum {
             tcx.hir()
                 .krate()
                 .item
-                .module
                 .item_ids
                 .iter()
                 .filter_map(|&id| {
@@ -354,7 +352,7 @@ impl Clean<Lifetime> for hir::Lifetime {
         match def {
             Some(
                 rl::Region::EarlyBound(_, node_id, _)
-                | rl::Region::LateBound(_, node_id, _)
+                | rl::Region::LateBound(_, _, node_id, _)
                 | rl::Region::Free(_, node_id),
             ) => {
                 if let Some(lt) = cx.lt_substs.get(&node_id).cloned() {
@@ -398,9 +396,7 @@ impl Clean<Constant> for hir::ConstArg {
                 .tcx
                 .type_of(cx.tcx.hir().body_owner_def_id(self.value.body).to_def_id())
                 .clean(cx),
-            expr: print_const_expr(cx.tcx, self.value.body),
-            value: None,
-            is_literal: is_literal_expr(cx, self.value.body.hir_id),
+            kind: ConstantKind::Anonymous { body: self.value.body },
         }
     }
 }
@@ -415,7 +411,7 @@ impl Clean<Option<Lifetime>> for ty::RegionKind {
     fn clean(&self, _cx: &mut DocContext<'_>) -> Option<Lifetime> {
         match *self {
             ty::ReStatic => Some(Lifetime::statik()),
-            ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name) }) => {
+            ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => {
                 Some(Lifetime(name))
             }
             ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)),
@@ -1135,7 +1131,7 @@ impl Clean<Item> for ty::AssocItem {
             ty::AssocKind::Const => {
                 let ty = tcx.type_of(self.def_id);
                 let default = if self.defaultness.has_value() {
-                    Some(inline::print_inlined_const(cx, self.def_id))
+                    Some(inline::print_inlined_const(tcx, self.def_id))
                 } else {
                     None
                 };
@@ -1745,11 +1741,10 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
 
 impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
+        // FIXME: instead of storing the stringified expression, store `self` directly instead.
         Constant {
             type_: self.ty.clean(cx),
-            expr: format!("{}", self),
-            value: None,
-            is_literal: false,
+            kind: ConstantKind::TyConst { expr: self.to_string() },
         }
     }
 }
@@ -1953,9 +1948,7 @@ impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
                 }
                 ItemKind::Const(ty, body_id) => ConstantItem(Constant {
                     type_: ty.clean(cx),
-                    expr: print_const_expr(cx.tcx, body_id),
-                    value: print_evaluated_const(cx, def_id),
-                    is_literal: is_literal_expr(cx, body_id.hir_id),
+                    kind: ConstantKind::Local { body: body_id, def_id },
                 }),
                 ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
                     bounds: ty.bounds.clean(cx),
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 142121b7346..4132e187c72 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -32,8 +32,9 @@ use rustc_target::spec::abi::Abi;
 
 use crate::clean::cfg::Cfg;
 use crate::clean::external_path;
-use crate::clean::inline;
+use crate::clean::inline::{self, print_inlined_const};
 use crate::clean::types::Type::{QPath, ResolvedPath};
+use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const};
 use crate::clean::Clean;
 use crate::core::DocContext;
 use crate::formats::cache::Cache;
@@ -1988,9 +1989,58 @@ crate struct Static {
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 crate struct Constant {
     crate type_: Type,
-    crate expr: String,
-    crate value: Option<String>,
-    crate is_literal: bool,
+    crate kind: ConstantKind,
+}
+
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+crate enum ConstantKind {
+    /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
+    /// `BodyId`, we need to handle it on its own.
+    ///
+    /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
+    /// by a DefId. So this field must be different from `Extern`.
+    TyConst { expr: String },
+    /// A constant (expression) that's not an item or associated item. These are usually found
+    /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
+    /// used to define explicit discriminant values for enum variants.
+    Anonymous { body: BodyId },
+    /// A constant from a different crate.
+    Extern { def_id: DefId },
+    /// `const FOO: u32 = ...;`
+    Local { def_id: DefId, body: BodyId },
+}
+
+impl Constant {
+    crate fn expr(&self, tcx: TyCtxt<'_>) -> String {
+        match self.kind {
+            ConstantKind::TyConst { ref expr } => expr.clone(),
+            ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
+            ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
+                print_const_expr(tcx, body)
+            }
+        }
+    }
+
+    crate fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
+        match self.kind {
+            ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
+            ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
+                print_evaluated_const(tcx, def_id)
+            }
+        }
+    }
+
+    crate fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
+        match self.kind {
+            ConstantKind::TyConst { .. } => false,
+            ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| {
+                is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id))
+            }),
+            ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
+                is_literal_expr(tcx, body.hir_id)
+            }
+        }
+    }
 }
 
 #[derive(Clone, Debug)]
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 582cbf69ed1..60cbe9f376f 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -97,7 +97,7 @@ fn external_generic_args(
         .iter()
         .filter_map(|kind| match kind.unpack() {
             GenericArgKind::Lifetime(lt) => match lt {
-                ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrAnon(_) }) => {
+                ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrAnon(_), .. }) => {
                     Some(GenericArg::Lifetime(Lifetime::elided()))
                 }
                 _ => lt.clean(cx).map(GenericArg::Lifetime),
@@ -301,7 +301,7 @@ crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
                 let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def.did);
                 print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(hir_id))
             } else {
-                inline::print_inlined_const(cx, def.did)
+                inline::print_inlined_const(cx.tcx, def.did)
             };
             if let Some(promoted) = promoted {
                 s.push_str(&format!("::{:?}", promoted))
@@ -324,15 +324,15 @@ crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
     }
 }
 
-crate fn print_evaluated_const(cx: &DocContext<'_>, def_id: DefId) -> Option<String> {
-    cx.tcx.const_eval_poly(def_id).ok().and_then(|val| {
-        let ty = cx.tcx.type_of(def_id);
+crate fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<String> {
+    tcx.const_eval_poly(def_id).ok().and_then(|val| {
+        let ty = tcx.type_of(def_id);
         match (val, ty.kind()) {
             (_, &ty::Ref(..)) => None,
             (ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
             (ConstValue::Scalar(_), _) => {
-                let const_ = ty::Const::from_value(cx.tcx, val, ty);
-                Some(print_const_with_custom_print_scalar(cx, const_))
+                let const_ = ty::Const::from_value(tcx, val, ty);
+                Some(print_const_with_custom_print_scalar(tcx, const_))
             }
             _ => None,
         }
@@ -349,7 +349,7 @@ fn format_integer_with_underscore_sep(num: &str) -> String {
         .collect()
 }
 
-fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const<'tcx>) -> String {
+fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tcx>) -> String {
     // Use a slightly different format for integer types which always shows the actual value.
     // For all other types, fallback to the original `pretty_print_const`.
     match (ct.val, ct.ty.kind()) {
@@ -357,8 +357,8 @@ fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const
             format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
         }
         (ty::ConstKind::Value(ConstValue::Scalar(int)), ty::Int(i)) => {
-            let ty = cx.tcx.lift(ct.ty).unwrap();
-            let size = cx.tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
+            let ty = tcx.lift(ct.ty).unwrap();
+            let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
             let data = int.assert_bits(size);
             let sign_extended_data = size.sign_extend(data) as i128;
 
@@ -372,8 +372,8 @@ fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const
     }
 }
 
-crate fn is_literal_expr(cx: &DocContext<'_>, hir_id: hir::HirId) -> bool {
-    if let hir::Node::Expr(expr) = cx.tcx.hir().get(hir_id) {
+crate fn is_literal_expr(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
+    if let hir::Node::Expr(expr) = tcx.hir().get(hir_id) {
         if let hir::ExprKind::Lit(_) = &expr.kind {
             return true;
         }
@@ -411,7 +411,7 @@ crate fn resolve_type(cx: &mut DocContext<'_>, path: Path, id: hir::HirId) -> Ty
             return Generic(kw::SelfUpper);
         }
         Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => {
-            return Generic(Symbol::intern(&format!("{:#}", path.print(&cx.cache))));
+            return Generic(Symbol::intern(&format!("{:#}", path.print(&cx.cache, cx.tcx))));
         }
         Res::SelfTy(..) | Res::Def(DefKind::TyParam | DefKind::AssocTy, _) => true,
         _ => false,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index d9e97e02a14..3d0ef028902 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -141,7 +141,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
                 hir_collector.visit_testable(
                     "".to_string(),
                     CRATE_HIR_ID,
-                    krate.item.span,
+                    krate.item.inner,
                     |this| {
                         intravisit::walk_crate(this, krate);
                     },
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index f9a663b38eb..01bceb1d910 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -227,7 +227,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
         if let clean::TraitItem(ref t) = *item.kind {
             self.cache.traits.entry(item.def_id).or_insert_with(|| clean::TraitWithExtraInfo {
                 trait_: t.clone(),
-                is_spotlight: item.attrs.has_doc_flag(sym::spotlight),
+                is_spotlight: item.attrs.has_doc_flag(sym::notable_trait),
             });
         }
 
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index f0b390add73..ae97cd64fb5 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -13,6 +13,11 @@ crate trait FormatRenderer<'tcx>: Sized {
     /// Gives a description of the renderer. Used for performance profiling.
     fn descr() -> &'static str;
 
+    /// Whether to call `item` recursivly for modules
+    ///
+    /// This is true for html, and false for json. See #80664
+    const RUN_ON_MODULE: bool;
+
     /// Sets up any state required for the renderer. When this is called the cache has already been
     /// populated.
     fn init(
@@ -73,7 +78,7 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
 
     let unknown = Symbol::intern("<unknown item>");
     while let Some((mut cx, item)) = work.pop() {
-        if item.is_mod() {
+        if item.is_mod() && T::RUN_ON_MODULE {
             // modules are special because they add a namespace. We also need to
             // recurse into the items of the module as well.
             let name = item.name.as_ref().unwrap().to_string();
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 60106f3b7ae..a004ee5054e 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -5,10 +5,10 @@
 //! assume that HTML output is desired, although it may be possible to redesign
 //! them in the future to instead emit any format desired.
 
-use std::borrow::Cow;
 use std::cell::Cell;
 use std::fmt;
 
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_middle::ty::TyCtxt;
@@ -111,31 +111,6 @@ impl Buffer {
     }
 }
 
-/// Wrapper struct for properly emitting a function or method declaration.
-crate struct Function<'a> {
-    /// The declaration to emit.
-    crate decl: &'a clean::FnDecl,
-    /// The length of the function header and name. In other words, the number of characters in the
-    /// function declaration up to but not including the parentheses.
-    ///
-    /// Used to determine line-wrapping.
-    crate header_len: usize,
-    /// The number of spaces to indent each successive line with, if line-wrapping is necessary.
-    crate indent: usize,
-    /// Whether the function is async or not.
-    crate asyncness: hir::IsAsync,
-}
-
-/// Wrapper struct for emitting a where-clause from Generics.
-crate struct WhereClause<'a> {
-    /// The Generics from which to emit a where-clause.
-    crate gens: &'a clean::Generics,
-    /// The number of spaces to indent each line with.
-    crate indent: usize,
-    /// Whether the where-clause needs to add a comma and newline after the last bound.
-    crate end_newline: bool,
-}
-
 fn comma_sep<T: fmt::Display>(items: impl Iterator<Item = T>) -> impl fmt::Display {
     display_fn(move |f| {
         for (i, item) in items.enumerate() {
@@ -148,27 +123,32 @@ fn comma_sep<T: fmt::Display>(items: impl Iterator<Item = T>) -> impl fmt::Displ
     })
 }
 
-crate fn print_generic_bounds<'a>(
+crate fn print_generic_bounds<'a, 'tcx: 'a>(
     bounds: &'a [clean::GenericBound],
     cache: &'a Cache,
-) -> impl fmt::Display + 'a {
+    tcx: TyCtxt<'tcx>,
+) -> impl fmt::Display + 'a + Captures<'tcx> {
     display_fn(move |f| {
         let mut bounds_dup = FxHashSet::default();
 
         for (i, bound) in
-            bounds.iter().filter(|b| bounds_dup.insert(b.print(cache).to_string())).enumerate()
+            bounds.iter().filter(|b| bounds_dup.insert(b.print(cache, tcx).to_string())).enumerate()
         {
             if i > 0 {
                 f.write_str(" + ")?;
             }
-            fmt::Display::fmt(&bound.print(cache), f)?;
+            fmt::Display::fmt(&bound.print(cache, tcx), f)?;
         }
         Ok(())
     })
 }
 
 impl clean::GenericParamDef {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a, 'tcx: 'a>(
+        &'a self,
+        cache: &'a Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'a + Captures<'tcx> {
         display_fn(move |f| match self.kind {
             clean::GenericParamDefKind::Lifetime => write!(f, "{}", self.name),
             clean::GenericParamDefKind::Type { ref bounds, ref default, .. } => {
@@ -176,17 +156,17 @@ impl clean::GenericParamDef {
 
                 if !bounds.is_empty() {
                     if f.alternate() {
-                        write!(f, ": {:#}", print_generic_bounds(bounds, cache))?;
+                        write!(f, ": {:#}", print_generic_bounds(bounds, cache, tcx))?;
                     } else {
-                        write!(f, ":&nbsp;{}", print_generic_bounds(bounds, cache))?;
+                        write!(f, ":&nbsp;{}", print_generic_bounds(bounds, cache, tcx))?;
                     }
                 }
 
                 if let Some(ref ty) = default {
                     if f.alternate() {
-                        write!(f, " = {:#}", ty.print(cache))?;
+                        write!(f, " = {:#}", ty.print(cache, tcx))?;
                     } else {
-                        write!(f, "&nbsp;=&nbsp;{}", ty.print(cache))?;
+                        write!(f, "&nbsp;=&nbsp;{}", ty.print(cache, tcx))?;
                     }
                 }
 
@@ -194,9 +174,9 @@ impl clean::GenericParamDef {
             }
             clean::GenericParamDefKind::Const { ref ty, .. } => {
                 if f.alternate() {
-                    write!(f, "const {}: {:#}", self.name, ty.print(cache))
+                    write!(f, "const {}: {:#}", self.name, ty.print(cache, tcx))
                 } else {
-                    write!(f, "const {}:&nbsp;{}", self.name, ty.print(cache))
+                    write!(f, "const {}:&nbsp;{}", self.name, ty.print(cache, tcx))
                 }
             }
         })
@@ -204,7 +184,11 @@ impl clean::GenericParamDef {
 }
 
 impl clean::Generics {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a, 'tcx: 'a>(
+        &'a self,
+        cache: &'a Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'a + Captures<'tcx> {
         display_fn(move |f| {
             let real_params =
                 self.params.iter().filter(|p| !p.is_synthetic_type_param()).collect::<Vec<_>>();
@@ -212,109 +196,115 @@ impl clean::Generics {
                 return Ok(());
             }
             if f.alternate() {
-                write!(f, "<{:#}>", comma_sep(real_params.iter().map(|g| g.print(cache))))
+                write!(f, "<{:#}>", comma_sep(real_params.iter().map(|g| g.print(cache, tcx))))
             } else {
-                write!(f, "&lt;{}&gt;", comma_sep(real_params.iter().map(|g| g.print(cache))))
+                write!(f, "&lt;{}&gt;", comma_sep(real_params.iter().map(|g| g.print(cache, tcx))))
             }
         })
     }
 }
 
-impl<'a> WhereClause<'a> {
-    crate fn print<'b>(&'b self, cache: &'b Cache) -> impl fmt::Display + 'b {
-        display_fn(move |f| {
-            let &WhereClause { gens, indent, end_newline } = self;
-            if gens.where_predicates.is_empty() {
-                return Ok(());
+/// * The Generics from which to emit a where-clause.
+/// * The number of spaces to indent each line with.
+/// * Whether the where-clause needs to add a comma and newline after the last bound.
+crate fn print_where_clause<'a, 'tcx: 'a>(
+    gens: &'a clean::Generics,
+    cache: &'a Cache,
+    tcx: TyCtxt<'tcx>,
+    indent: usize,
+    end_newline: bool,
+) -> impl fmt::Display + 'a + Captures<'tcx> {
+    display_fn(move |f| {
+        if gens.where_predicates.is_empty() {
+            return Ok(());
+        }
+        let mut clause = String::new();
+        if f.alternate() {
+            clause.push_str(" where");
+        } else {
+            if end_newline {
+                clause.push_str(" <span class=\"where fmt-newline\">where");
+            } else {
+                clause.push_str(" <span class=\"where\">where");
             }
-            let mut clause = String::new();
+        }
+        for (i, pred) in gens.where_predicates.iter().enumerate() {
             if f.alternate() {
-                clause.push_str(" where");
+                clause.push(' ');
             } else {
-                if end_newline {
-                    clause.push_str(" <span class=\"where fmt-newline\">where");
-                } else {
-                    clause.push_str(" <span class=\"where\">where");
-                }
+                clause.push_str("<br>");
             }
-            for (i, pred) in gens.where_predicates.iter().enumerate() {
-                if f.alternate() {
-                    clause.push(' ');
-                } else {
-                    clause.push_str("<br>");
-                }
 
-                match pred {
-                    clean::WherePredicate::BoundPredicate { ty, bounds } => {
-                        let bounds = bounds;
-                        if f.alternate() {
-                            clause.push_str(&format!(
-                                "{:#}: {:#}",
-                                ty.print(cache),
-                                print_generic_bounds(bounds, cache)
-                            ));
-                        } else {
-                            clause.push_str(&format!(
-                                "{}: {}",
-                                ty.print(cache),
-                                print_generic_bounds(bounds, cache)
-                            ));
-                        }
-                    }
-                    clean::WherePredicate::RegionPredicate { lifetime, bounds } => {
+            match pred {
+                clean::WherePredicate::BoundPredicate { ty, bounds } => {
+                    let bounds = bounds;
+                    if f.alternate() {
+                        clause.push_str(&format!(
+                            "{:#}: {:#}",
+                            ty.print(cache, tcx),
+                            print_generic_bounds(bounds, cache, tcx)
+                        ));
+                    } else {
                         clause.push_str(&format!(
                             "{}: {}",
-                            lifetime.print(),
-                            bounds
-                                .iter()
-                                .map(|b| b.print(cache).to_string())
-                                .collect::<Vec<_>>()
-                                .join(" + ")
+                            ty.print(cache, tcx),
+                            print_generic_bounds(bounds, cache, tcx)
                         ));
                     }
-                    clean::WherePredicate::EqPredicate { lhs, rhs } => {
-                        if f.alternate() {
-                            clause.push_str(&format!(
-                                "{:#} == {:#}",
-                                lhs.print(cache),
-                                rhs.print(cache)
-                            ));
-                        } else {
-                            clause.push_str(&format!(
-                                "{} == {}",
-                                lhs.print(cache),
-                                rhs.print(cache)
-                            ));
-                        }
+                }
+                clean::WherePredicate::RegionPredicate { lifetime, bounds } => {
+                    clause.push_str(&format!(
+                        "{}: {}",
+                        lifetime.print(),
+                        bounds
+                            .iter()
+                            .map(|b| b.print(cache, tcx).to_string())
+                            .collect::<Vec<_>>()
+                            .join(" + ")
+                    ));
+                }
+                clean::WherePredicate::EqPredicate { lhs, rhs } => {
+                    if f.alternate() {
+                        clause.push_str(&format!(
+                            "{:#} == {:#}",
+                            lhs.print(cache, tcx),
+                            rhs.print(cache, tcx),
+                        ));
+                    } else {
+                        clause.push_str(&format!(
+                            "{} == {}",
+                            lhs.print(cache, tcx),
+                            rhs.print(cache, tcx),
+                        ));
                     }
                 }
+            }
 
-                if i < gens.where_predicates.len() - 1 || end_newline {
-                    clause.push(',');
-                }
+            if i < gens.where_predicates.len() - 1 || end_newline {
+                clause.push(',');
             }
+        }
 
-            if end_newline {
-                // add a space so stripping <br> tags and breaking spaces still renders properly
-                if f.alternate() {
-                    clause.push(' ');
-                } else {
-                    clause.push_str("&nbsp;");
-                }
+        if end_newline {
+            // add a space so stripping <br> tags and breaking spaces still renders properly
+            if f.alternate() {
+                clause.push(' ');
+            } else {
+                clause.push_str("&nbsp;");
             }
+        }
 
-            if !f.alternate() {
-                clause.push_str("</span>");
-                let padding = "&nbsp;".repeat(indent + 4);
-                clause = clause.replace("<br>", &format!("<br>{}", padding));
-                clause.insert_str(0, &"&nbsp;".repeat(indent.saturating_sub(1)));
-                if !end_newline {
-                    clause.insert_str(0, "<br>");
-                }
+        if !f.alternate() {
+            clause.push_str("</span>");
+            let padding = "&nbsp;".repeat(indent + 4);
+            clause = clause.replace("<br>", &format!("<br>{}", padding));
+            clause.insert_str(0, &"&nbsp;".repeat(indent.saturating_sub(1)));
+            if !end_newline {
+                clause.insert_str(0, "<br>");
             }
-            write!(f, "{}", clause)
-        })
-    }
+        }
+        write!(f, "{}", clause)
+    })
 }
 
 impl clean::Lifetime {
@@ -324,46 +314,53 @@ impl clean::Lifetime {
 }
 
 impl clean::Constant {
-    crate fn print(&self) -> impl fmt::Display + '_ {
-        display_fn(move |f| {
-            if f.alternate() {
-                f.write_str(&self.expr)
-            } else {
-                write!(f, "{}", Escape(&self.expr))
-            }
-        })
+    crate fn print(&self, tcx: TyCtxt<'_>) -> impl fmt::Display + '_ {
+        let expr = self.expr(tcx);
+        display_fn(
+            move |f| {
+                if f.alternate() { f.write_str(&expr) } else { write!(f, "{}", Escape(&expr)) }
+            },
+        )
     }
 }
 
 impl clean::PolyTrait {
-    fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    fn print<'a, 'tcx: 'a>(
+        &'a self,
+        cache: &'a Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'a + Captures<'tcx> {
         display_fn(move |f| {
             if !self.generic_params.is_empty() {
                 if f.alternate() {
                     write!(
                         f,
                         "for<{:#}> ",
-                        comma_sep(self.generic_params.iter().map(|g| g.print(cache)))
+                        comma_sep(self.generic_params.iter().map(|g| g.print(cache, tcx)))
                     )?;
                 } else {
                     write!(
                         f,
                         "for&lt;{}&gt; ",
-                        comma_sep(self.generic_params.iter().map(|g| g.print(cache)))
+                        comma_sep(self.generic_params.iter().map(|g| g.print(cache, tcx)))
                     )?;
                 }
             }
             if f.alternate() {
-                write!(f, "{:#}", self.trait_.print(cache))
+                write!(f, "{:#}", self.trait_.print(cache, tcx))
             } else {
-                write!(f, "{}", self.trait_.print(cache))
+                write!(f, "{}", self.trait_.print(cache, tcx))
             }
         })
     }
 }
 
 impl clean::GenericBound {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a, 'tcx: 'a>(
+        &'a self,
+        cache: &'a Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'a + Captures<'tcx> {
         display_fn(move |f| match self {
             clean::GenericBound::Outlives(lt) => write!(f, "{}", lt.print()),
             clean::GenericBound::TraitBound(ty, modifier) => {
@@ -373,9 +370,9 @@ impl clean::GenericBound {
                     hir::TraitBoundModifier::MaybeConst => "?const",
                 };
                 if f.alternate() {
-                    write!(f, "{}{:#}", modifier_str, ty.print(cache))
+                    write!(f, "{}{:#}", modifier_str, ty.print(cache, tcx))
                 } else {
-                    write!(f, "{}{}", modifier_str, ty.print(cache))
+                    write!(f, "{}{}", modifier_str, ty.print(cache, tcx))
                 }
             }
         })
@@ -383,7 +380,11 @@ impl clean::GenericBound {
 }
 
 impl clean::GenericArgs {
-    fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    fn print<'a, 'tcx: 'a>(
+        &'a self,
+        cache: &'a Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'a + Captures<'tcx> {
         display_fn(move |f| {
             match self {
                 clean::GenericArgs::AngleBracketed { args, bindings } => {
@@ -400,9 +401,9 @@ impl clean::GenericArgs {
                             }
                             comma = true;
                             if f.alternate() {
-                                write!(f, "{:#}", arg.print(cache))?;
+                                write!(f, "{:#}", arg.print(cache, tcx))?;
                             } else {
-                                write!(f, "{}", arg.print(cache))?;
+                                write!(f, "{}", arg.print(cache, tcx))?;
                             }
                         }
                         for binding in bindings {
@@ -411,9 +412,9 @@ impl clean::GenericArgs {
                             }
                             comma = true;
                             if f.alternate() {
-                                write!(f, "{:#}", binding.print(cache))?;
+                                write!(f, "{:#}", binding.print(cache, tcx))?;
                             } else {
-                                write!(f, "{}", binding.print(cache))?;
+                                write!(f, "{}", binding.print(cache, tcx))?;
                             }
                         }
                         if f.alternate() {
@@ -432,17 +433,17 @@ impl clean::GenericArgs {
                         }
                         comma = true;
                         if f.alternate() {
-                            write!(f, "{:#}", ty.print(cache))?;
+                            write!(f, "{:#}", ty.print(cache, tcx))?;
                         } else {
-                            write!(f, "{}", ty.print(cache))?;
+                            write!(f, "{}", ty.print(cache, tcx))?;
                         }
                     }
                     f.write_str(")")?;
                     if let Some(ref ty) = *output {
                         if f.alternate() {
-                            write!(f, " -> {:#}", ty.print(cache))?;
+                            write!(f, " -> {:#}", ty.print(cache, tcx))?;
                         } else {
-                            write!(f, " -&gt; {}", ty.print(cache))?;
+                            write!(f, " -&gt; {}", ty.print(cache, tcx))?;
                         }
                     }
                 }
@@ -453,19 +454,27 @@ impl clean::GenericArgs {
 }
 
 impl clean::PathSegment {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a, 'tcx: 'a>(
+        &'a self,
+        cache: &'a Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'a + Captures<'tcx> {
         display_fn(move |f| {
             if f.alternate() {
-                write!(f, "{}{:#}", self.name, self.args.print(cache))
+                write!(f, "{}{:#}", self.name, self.args.print(cache, tcx))
             } else {
-                write!(f, "{}{}", self.name, self.args.print(cache))
+                write!(f, "{}{}", self.name, self.args.print(cache, tcx))
             }
         })
     }
 }
 
 impl clean::Path {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a, 'tcx: 'a>(
+        &'a self,
+        cache: &'a Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'a + Captures<'tcx> {
         display_fn(move |f| {
             if self.global {
                 f.write_str("::")?
@@ -476,9 +485,9 @@ impl clean::Path {
                     f.write_str("::")?
                 }
                 if f.alternate() {
-                    write!(f, "{:#}", seg.print(cache))?;
+                    write!(f, "{:#}", seg.print(cache, tcx))?;
                 } else {
-                    write!(f, "{}", seg.print(cache))?;
+                    write!(f, "{}", seg.print(cache, tcx))?;
                 }
             }
             Ok(())
@@ -528,13 +537,14 @@ crate fn href(did: DefId, cache: &Cache) -> Option<(String, ItemType, Vec<String
 
 /// Used when rendering a `ResolvedPath` structure. This invokes the `path`
 /// rendering function with the necessary arguments for linking to a local path.
-fn resolved_path(
+fn resolved_path<'a, 'tcx: 'a>(
     w: &mut fmt::Formatter<'_>,
     did: DefId,
     path: &clean::Path,
     print_all: bool,
     use_absolute: bool,
     cache: &Cache,
+    tcx: TyCtxt<'tcx>,
 ) -> fmt::Result {
     let last = path.segments.last().unwrap();
 
@@ -544,7 +554,7 @@ fn resolved_path(
         }
     }
     if w.alternate() {
-        write!(w, "{}{:#}", &last.name, last.args.print(cache))?;
+        write!(w, "{}{:#}", &last.name, last.args.print(cache, tcx))?;
     } else {
         let path = if use_absolute {
             if let Some((_, _, fqp)) = href(did, cache) {
@@ -559,7 +569,7 @@ fn resolved_path(
         } else {
             anchor(did, &*last.name.as_str(), cache).to_string()
         };
-        write!(w, "{}{}", path, last.args.print(cache))?;
+        write!(w, "{}{}", path, last.args.print(cache, tcx))?;
     }
     Ok(())
 }
@@ -615,15 +625,16 @@ fn primitive_link(
 }
 
 /// Helper to render type parameters
-fn tybounds<'a>(
+fn tybounds<'a, 'tcx: 'a>(
     param_names: &'a Option<Vec<clean::GenericBound>>,
     cache: &'a Cache,
-) -> impl fmt::Display + 'a {
+    tcx: TyCtxt<'tcx>,
+) -> impl fmt::Display + 'a + Captures<'tcx> {
     display_fn(move |f| match *param_names {
         Some(ref params) => {
             for param in params {
                 write!(f, " + ")?;
-                fmt::Display::fmt(&param.print(cache), f)?;
+                fmt::Display::fmt(&param.print(cache, tcx), f)?;
             }
             Ok(())
         }
@@ -654,6 +665,7 @@ fn fmt_type(
     f: &mut fmt::Formatter<'_>,
     use_absolute: bool,
     cache: &Cache,
+    tcx: TyCtxt<'_>,
 ) -> fmt::Result {
     debug!("fmt_type(t = {:?})", t);
 
@@ -664,8 +676,8 @@ fn fmt_type(
                 f.write_str("dyn ")?;
             }
             // Paths like `T::Output` and `Self::Output` should be rendered with all segments.
-            resolved_path(f, did, path, is_generic, use_absolute, cache)?;
-            fmt::Display::fmt(&tybounds(param_names, cache), f)
+            resolved_path(f, did, path, is_generic, use_absolute, cache, tcx)?;
+            fmt::Display::fmt(&tybounds(param_names, cache, tcx), f)
         }
         clean::Infer => write!(f, "_"),
         clean::Primitive(prim) => primitive_link(f, prim, prim.as_str(), cache),
@@ -674,21 +686,21 @@ fn fmt_type(
                 write!(
                     f,
                     "{:#}{}{:#}fn{:#}",
-                    decl.print_hrtb_with_space(cache),
+                    decl.print_hrtb_with_space(cache, tcx),
                     decl.unsafety.print_with_space(),
                     print_abi_with_space(decl.abi),
-                    decl.decl.print(cache)
+                    decl.decl.print(cache, tcx),
                 )
             } else {
                 write!(
                     f,
                     "{}{}{}",
-                    decl.print_hrtb_with_space(cache),
+                    decl.print_hrtb_with_space(cache, tcx),
                     decl.unsafety.print_with_space(),
                     print_abi_with_space(decl.abi)
                 )?;
                 primitive_link(f, PrimitiveType::Fn, "fn", cache)?;
-                write!(f, "{}", decl.decl.print(cache))
+                write!(f, "{}", decl.decl.print(cache, tcx))
             }
         }
         clean::Tuple(ref typs) => {
@@ -697,7 +709,7 @@ fn fmt_type(
                 &[ref one] => {
                     primitive_link(f, PrimitiveType::Tuple, "(", cache)?;
                     // Carry `f.alternate()` into this display w/o branching manually.
-                    fmt::Display::fmt(&one.print(cache), f)?;
+                    fmt::Display::fmt(&one.print(cache, tcx), f)?;
                     primitive_link(f, PrimitiveType::Tuple, ",)", cache)
                 }
                 many => {
@@ -706,7 +718,7 @@ fn fmt_type(
                         if i != 0 {
                             write!(f, ", ")?;
                         }
-                        fmt::Display::fmt(&item.print(cache), f)?;
+                        fmt::Display::fmt(&item.print(cache, tcx), f)?;
                     }
                     primitive_link(f, PrimitiveType::Tuple, ")", cache)
                 }
@@ -714,12 +726,12 @@ fn fmt_type(
         }
         clean::Slice(ref t) => {
             primitive_link(f, PrimitiveType::Slice, "[", cache)?;
-            fmt::Display::fmt(&t.print(cache), f)?;
+            fmt::Display::fmt(&t.print(cache, tcx), f)?;
             primitive_link(f, PrimitiveType::Slice, "]", cache)
         }
         clean::Array(ref t, ref n) => {
             primitive_link(f, PrimitiveType::Array, "[", cache)?;
-            fmt::Display::fmt(&t.print(cache), f)?;
+            fmt::Display::fmt(&t.print(cache, tcx), f)?;
             if f.alternate() {
                 primitive_link(f, PrimitiveType::Array, &format!("; {}]", n), cache)
             } else {
@@ -738,14 +750,14 @@ fn fmt_type(
                         primitive_link(
                             f,
                             clean::PrimitiveType::RawPointer,
-                            &format!("*{} {:#}", m, t.print(cache)),
+                            &format!("*{} {:#}", m, t.print(cache, tcx)),
                             cache,
                         )
                     } else {
                         primitive_link(
                             f,
                             clean::PrimitiveType::RawPointer,
-                            &format!("*{} {}", m, t.print(cache)),
+                            &format!("*{} {}", m, t.print(cache, tcx)),
                             cache,
                         )
                     }
@@ -757,7 +769,7 @@ fn fmt_type(
                         &format!("*{} ", m),
                         cache,
                     )?;
-                    fmt::Display::fmt(&t.print(cache), f)
+                    fmt::Display::fmt(&t.print(cache, tcx), f)
                 }
             }
         }
@@ -777,14 +789,14 @@ fn fmt_type(
                                 primitive_link(
                                     f,
                                     PrimitiveType::Slice,
-                                    &format!("{}{}{}[{:#}]", amp, lt, m, bt.print(cache)),
+                                    &format!("{}{}{}[{:#}]", amp, lt, m, bt.print(cache, tcx)),
                                     cache,
                                 )
                             } else {
                                 primitive_link(
                                     f,
                                     PrimitiveType::Slice,
-                                    &format!("{}{}{}[{}]", amp, lt, m, bt.print(cache)),
+                                    &format!("{}{}{}[{}]", amp, lt, m, bt.print(cache, tcx)),
                                     cache,
                                 )
                             }
@@ -797,9 +809,9 @@ fn fmt_type(
                                 cache,
                             )?;
                             if f.alternate() {
-                                write!(f, "{:#}", bt.print(cache))?;
+                                write!(f, "{:#}", bt.print(cache, tcx))?;
                             } else {
-                                write!(f, "{}", bt.print(cache))?;
+                                write!(f, "{}", bt.print(cache, tcx))?;
                             }
                             primitive_link(f, PrimitiveType::Slice, "]", cache)
                         }
@@ -807,7 +819,7 @@ fn fmt_type(
                 }
                 clean::ResolvedPath { param_names: Some(ref v), .. } if !v.is_empty() => {
                     write!(f, "{}{}{}(", amp, lt, m)?;
-                    fmt_type(&ty, f, use_absolute, cache)?;
+                    fmt_type(&ty, f, use_absolute, cache, tcx)?;
                     write!(f, ")")
                 }
                 clean::Generic(..) => {
@@ -817,19 +829,19 @@ fn fmt_type(
                         &format!("{}{}{}", amp, lt, m),
                         cache,
                     )?;
-                    fmt_type(&ty, f, use_absolute, cache)
+                    fmt_type(&ty, f, use_absolute, cache, tcx)
                 }
                 _ => {
                     write!(f, "{}{}{}", amp, lt, m)?;
-                    fmt_type(&ty, f, use_absolute, cache)
+                    fmt_type(&ty, f, use_absolute, cache, tcx)
                 }
             }
         }
         clean::ImplTrait(ref bounds) => {
             if f.alternate() {
-                write!(f, "impl {:#}", print_generic_bounds(bounds, cache))
+                write!(f, "impl {:#}", print_generic_bounds(bounds, cache, tcx))
             } else {
-                write!(f, "impl {}", print_generic_bounds(bounds, cache))
+                write!(f, "impl {}", print_generic_bounds(bounds, cache, tcx))
             }
         }
         clean::QPath { ref name, ref self_type, ref trait_ } => {
@@ -841,15 +853,25 @@ fn fmt_type(
             };
             if f.alternate() {
                 if should_show_cast {
-                    write!(f, "<{:#} as {:#}>::", self_type.print(cache), trait_.print(cache))?
+                    write!(
+                        f,
+                        "<{:#} as {:#}>::",
+                        self_type.print(cache, tcx),
+                        trait_.print(cache, tcx)
+                    )?
                 } else {
-                    write!(f, "{:#}::", self_type.print(cache))?
+                    write!(f, "{:#}::", self_type.print(cache, tcx))?
                 }
             } else {
                 if should_show_cast {
-                    write!(f, "&lt;{} as {}&gt;::", self_type.print(cache), trait_.print(cache))?
+                    write!(
+                        f,
+                        "&lt;{} as {}&gt;::",
+                        self_type.print(cache, tcx),
+                        trait_.print(cache, tcx)
+                    )?
                 } else {
-                    write!(f, "{}::", self_type.print(cache))?
+                    write!(f, "{}::", self_type.print(cache, tcx))?
                 }
             };
             match *trait_ {
@@ -890,52 +912,64 @@ fn fmt_type(
 }
 
 impl clean::Type {
-    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
-        display_fn(move |f| fmt_type(self, f, false, cache))
+    crate fn print<'b, 'a: 'b, 'tcx: 'a>(
+        &'a self,
+        cache: &'b Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'b + Captures<'tcx> {
+        display_fn(move |f| fmt_type(self, f, false, cache, tcx))
     }
 }
 
 impl clean::Impl {
-    crate fn print<'a>(&'a self, cache: &'a Cache, use_absolute: bool) -> impl fmt::Display + 'a {
+    crate fn print<'a, 'tcx: 'a>(
+        &'a self,
+        cache: &'a Cache,
+        use_absolute: bool,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'a + Captures<'tcx> {
         display_fn(move |f| {
             if f.alternate() {
-                write!(f, "impl{:#} ", self.generics.print(cache))?;
+                write!(f, "impl{:#} ", self.generics.print(cache, tcx))?;
             } else {
-                write!(f, "impl{} ", self.generics.print(cache))?;
+                write!(f, "impl{} ", self.generics.print(cache, tcx))?;
             }
 
             if let Some(ref ty) = self.trait_ {
                 if self.negative_polarity {
                     write!(f, "!")?;
                 }
-                fmt::Display::fmt(&ty.print(cache), f)?;
+                fmt::Display::fmt(&ty.print(cache, tcx), f)?;
                 write!(f, " for ")?;
             }
 
             if let Some(ref ty) = self.blanket_impl {
-                fmt_type(ty, f, use_absolute, cache)?;
+                fmt_type(ty, f, use_absolute, cache, tcx)?;
             } else {
-                fmt_type(&self.for_, f, use_absolute, cache)?;
+                fmt_type(&self.for_, f, use_absolute, cache, tcx)?;
             }
 
-            let where_clause = WhereClause { gens: &self.generics, indent: 0, end_newline: true };
-            fmt::Display::fmt(&where_clause.print(cache), f)?;
+            fmt::Display::fmt(&print_where_clause(&self.generics, cache, tcx, 0, true), f)?;
             Ok(())
         })
     }
 }
 
 impl clean::Arguments {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a, 'tcx: 'a>(
+        &'a self,
+        cache: &'a Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'a + Captures<'tcx> {
         display_fn(move |f| {
             for (i, input) in self.values.iter().enumerate() {
                 if !input.name.is_empty() {
                     write!(f, "{}: ", input.name)?;
                 }
                 if f.alternate() {
-                    write!(f, "{:#}", input.type_.print(cache))?;
+                    write!(f, "{:#}", input.type_.print(cache, tcx))?;
                 } else {
-                    write!(f, "{}", input.type_.print(cache))?;
+                    write!(f, "{}", input.type_.print(cache, tcx))?;
                 }
                 if i + 1 < self.values.len() {
                     write!(f, ", ")?;
@@ -947,21 +981,33 @@ impl clean::Arguments {
 }
 
 impl clean::FnRetTy {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a, 'tcx: 'a>(
+        &'a self,
+        cache: &'a Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'a + Captures<'tcx> {
         display_fn(move |f| match self {
             clean::Return(clean::Tuple(tys)) if tys.is_empty() => Ok(()),
-            clean::Return(ty) if f.alternate() => write!(f, " -> {:#}", ty.print(cache)),
-            clean::Return(ty) => write!(f, " -&gt; {}", ty.print(cache)),
+            clean::Return(ty) if f.alternate() => write!(f, " -> {:#}", ty.print(cache, tcx)),
+            clean::Return(ty) => write!(f, " -&gt; {}", ty.print(cache, tcx)),
             clean::DefaultReturn => Ok(()),
         })
     }
 }
 
 impl clean::BareFunctionDecl {
-    fn print_hrtb_with_space<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    fn print_hrtb_with_space<'a, 'tcx: 'a>(
+        &'a self,
+        cache: &'a Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'a + Captures<'tcx> {
         display_fn(move |f| {
             if !self.generic_params.is_empty() {
-                write!(f, "for<{}> ", comma_sep(self.generic_params.iter().map(|g| g.print(cache))))
+                write!(
+                    f,
+                    "for<{}> ",
+                    comma_sep(self.generic_params.iter().map(|g| g.print(cache, tcx)))
+                )
             } else {
                 Ok(())
             }
@@ -970,147 +1016,176 @@ impl clean::BareFunctionDecl {
 }
 
 impl clean::FnDecl {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'b, 'a: 'b, 'tcx: 'a>(
+        &'a self,
+        cache: &'b Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'b + Captures<'tcx> {
         display_fn(move |f| {
             let ellipsis = if self.c_variadic { ", ..." } else { "" };
             if f.alternate() {
                 write!(
                     f,
                     "({args:#}{ellipsis}){arrow:#}",
-                    args = self.inputs.print(cache),
+                    args = self.inputs.print(cache, tcx),
                     ellipsis = ellipsis,
-                    arrow = self.output.print(cache)
+                    arrow = self.output.print(cache, tcx)
                 )
             } else {
                 write!(
                     f,
                     "({args}{ellipsis}){arrow}",
-                    args = self.inputs.print(cache),
+                    args = self.inputs.print(cache, tcx),
                     ellipsis = ellipsis,
-                    arrow = self.output.print(cache)
+                    arrow = self.output.print(cache, tcx)
                 )
             }
         })
     }
-}
 
-impl Function<'_> {
-    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
-        display_fn(move |f| {
-            let &Function { decl, header_len, indent, asyncness } = self;
-            let amp = if f.alternate() { "&" } else { "&amp;" };
-            let mut args = String::new();
-            let mut args_plain = String::new();
-            for (i, input) in decl.inputs.values.iter().enumerate() {
-                if i == 0 {
-                    args.push_str("<br>");
-                }
+    /// * `header_len`: The length of the function header and name. In other words, the number of
+    ///   characters in the function declaration up to but not including the parentheses.
+    ///   <br>Used to determine line-wrapping.
+    /// * `indent`: The number of spaces to indent each successive line with, if line-wrapping is
+    ///   necessary.
+    /// * `asyncness`: Whether the function is async or not.
+    crate fn full_print<'b, 'a: 'b, 'tcx: 'a>(
+        &'a self,
+        cache: &'b Cache,
+        tcx: TyCtxt<'tcx>,
+        header_len: usize,
+        indent: usize,
+        asyncness: hir::IsAsync,
+    ) -> impl fmt::Display + 'b + Captures<'tcx> {
+        display_fn(move |f| self.inner_full_print(cache, tcx, header_len, indent, asyncness, f))
+    }
 
-                if let Some(selfty) = input.to_self() {
-                    match selfty {
-                        clean::SelfValue => {
-                            args.push_str("self");
-                            args_plain.push_str("self");
-                        }
-                        clean::SelfBorrowed(Some(ref lt), mtbl) => {
-                            args.push_str(&format!(
-                                "{}{} {}self",
-                                amp,
-                                lt.print(),
-                                mtbl.print_with_space()
-                            ));
-                            args_plain.push_str(&format!(
-                                "&{} {}self",
-                                lt.print(),
-                                mtbl.print_with_space()
-                            ));
-                        }
-                        clean::SelfBorrowed(None, mtbl) => {
-                            args.push_str(&format!("{}{}self", amp, mtbl.print_with_space()));
-                            args_plain.push_str(&format!("&{}self", mtbl.print_with_space()));
-                        }
-                        clean::SelfExplicit(ref typ) => {
-                            if f.alternate() {
-                                args.push_str(&format!("self: {:#}", typ.print(cache)));
-                            } else {
-                                args.push_str(&format!("self: {}", typ.print(cache)));
-                            }
-                            args_plain.push_str(&format!("self: {:#}", typ.print(cache)));
-                        }
+    fn inner_full_print(
+        &self,
+        cache: &Cache,
+        tcx: TyCtxt<'_>,
+        header_len: usize,
+        indent: usize,
+        asyncness: hir::IsAsync,
+        f: &mut fmt::Formatter<'_>,
+    ) -> fmt::Result {
+        let amp = if f.alternate() { "&" } else { "&amp;" };
+        let mut args = String::new();
+        let mut args_plain = String::new();
+        for (i, input) in self.inputs.values.iter().enumerate() {
+            if i == 0 {
+                args.push_str("<br>");
+            }
+
+            if let Some(selfty) = input.to_self() {
+                match selfty {
+                    clean::SelfValue => {
+                        args.push_str("self");
+                        args_plain.push_str("self");
                     }
-                } else {
-                    if i > 0 {
-                        args.push_str(" <br>");
-                        args_plain.push(' ');
+                    clean::SelfBorrowed(Some(ref lt), mtbl) => {
+                        args.push_str(&format!(
+                            "{}{} {}self",
+                            amp,
+                            lt.print(),
+                            mtbl.print_with_space()
+                        ));
+                        args_plain.push_str(&format!(
+                            "&{} {}self",
+                            lt.print(),
+                            mtbl.print_with_space()
+                        ));
                     }
-                    if !input.name.is_empty() {
-                        args.push_str(&format!("{}: ", input.name));
-                        args_plain.push_str(&format!("{}: ", input.name));
+                    clean::SelfBorrowed(None, mtbl) => {
+                        args.push_str(&format!("{}{}self", amp, mtbl.print_with_space()));
+                        args_plain.push_str(&format!("&{}self", mtbl.print_with_space()));
                     }
-
-                    if f.alternate() {
-                        args.push_str(&format!("{:#}", input.type_.print(cache)));
-                    } else {
-                        args.push_str(&input.type_.print(cache).to_string());
+                    clean::SelfExplicit(ref typ) => {
+                        if f.alternate() {
+                            args.push_str(&format!("self: {:#}", typ.print(cache, tcx)));
+                        } else {
+                            args.push_str(&format!("self: {}", typ.print(cache, tcx)));
+                        }
+                        args_plain.push_str(&format!("self: {:#}", typ.print(cache, tcx)));
                     }
-                    args_plain.push_str(&format!("{:#}", input.type_.print(cache)));
                 }
-                if i + 1 < decl.inputs.values.len() {
-                    args.push(',');
-                    args_plain.push(',');
+            } else {
+                if i > 0 {
+                    args.push_str(" <br>");
+                    args_plain.push(' ');
+                }
+                if !input.name.is_empty() {
+                    args.push_str(&format!("{}: ", input.name));
+                    args_plain.push_str(&format!("{}: ", input.name));
                 }
-            }
-
-            let mut args_plain = format!("({})", args_plain);
 
-            if decl.c_variadic {
-                args.push_str(",<br> ...");
-                args_plain.push_str(", ...");
+                if f.alternate() {
+                    args.push_str(&format!("{:#}", input.type_.print(cache, tcx)));
+                } else {
+                    args.push_str(&input.type_.print(cache, tcx).to_string());
+                }
+                args_plain.push_str(&format!("{:#}", input.type_.print(cache, tcx)));
+            }
+            if i + 1 < self.inputs.values.len() {
+                args.push(',');
+                args_plain.push(',');
             }
+        }
 
-            let output = if let hir::IsAsync::Async = asyncness {
-                Cow::Owned(decl.sugared_async_return_type())
-            } else {
-                Cow::Borrowed(&decl.output)
-            };
+        let mut args_plain = format!("({})", args_plain);
 
-            let arrow_plain = format!("{:#}", &output.print(cache));
-            let arrow = if f.alternate() {
-                format!("{:#}", &output.print(cache))
-            } else {
-                output.print(cache).to_string()
-            };
+        if self.c_variadic {
+            args.push_str(",<br> ...");
+            args_plain.push_str(", ...");
+        }
 
-            let declaration_len = header_len + args_plain.len() + arrow_plain.len();
-            let output = if declaration_len > 80 {
-                let full_pad = format!("<br>{}", "&nbsp;".repeat(indent + 4));
-                let close_pad = format!("<br>{}", "&nbsp;".repeat(indent));
-                format!(
-                    "({args}{close}){arrow}",
-                    args = args.replace("<br>", &full_pad),
-                    close = close_pad,
-                    arrow = arrow
-                )
+        let arrow_plain;
+        let arrow = if let hir::IsAsync::Async = asyncness {
+            let output = self.sugared_async_return_type();
+            arrow_plain = format!("{:#}", output.print(cache, tcx));
+            if f.alternate() {
+                arrow_plain.clone()
             } else {
-                format!("({args}){arrow}", args = args.replace("<br>", ""), arrow = arrow)
-            };
-
+                format!("{}", output.print(cache, tcx))
+            }
+        } else {
+            arrow_plain = format!("{:#}", self.output.print(cache, tcx));
             if f.alternate() {
-                write!(f, "{}", output.replace("<br>", "\n"))
+                arrow_plain.clone()
             } else {
-                write!(f, "{}", output)
+                format!("{}", self.output.print(cache, tcx))
             }
-        })
+        };
+
+        let declaration_len = header_len + args_plain.len() + arrow_plain.len();
+        let output = if declaration_len > 80 {
+            let full_pad = format!("<br>{}", "&nbsp;".repeat(indent + 4));
+            let close_pad = format!("<br>{}", "&nbsp;".repeat(indent));
+            format!(
+                "({args}{close}){arrow}",
+                args = args.replace("<br>", &full_pad),
+                close = close_pad,
+                arrow = arrow
+            )
+        } else {
+            format!("({args}){arrow}", args = args.replace("<br>", ""), arrow = arrow)
+        };
+
+        if f.alternate() {
+            write!(f, "{}", output.replace("<br>", "\n"))
+        } else {
+            write!(f, "{}", output)
+        }
     }
 }
 
 impl clean::Visibility {
-    crate fn print_with_space<'tcx>(
+    crate fn print_with_space<'a, 'tcx: 'a>(
         self,
         tcx: TyCtxt<'tcx>,
         item_did: DefId,
-        cache: &Cache,
-    ) -> impl fmt::Display + 'tcx {
+        cache: &'a Cache,
+    ) -> impl fmt::Display + 'a + Captures<'tcx> {
         use rustc_span::symbol::kw;
 
         let to_print = match self {
@@ -1202,20 +1277,24 @@ impl PrintWithSpace for hir::Mutability {
 }
 
 impl clean::Import {
-    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
+    crate fn print<'b, 'a: 'b, 'tcx: 'a>(
+        &'a self,
+        cache: &'b Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'b + Captures<'tcx> {
         display_fn(move |f| match self.kind {
             clean::ImportKind::Simple(name) => {
                 if name == self.source.path.last() {
-                    write!(f, "use {};", self.source.print(cache))
+                    write!(f, "use {};", self.source.print(cache, tcx))
                 } else {
-                    write!(f, "use {} as {};", self.source.print(cache), name)
+                    write!(f, "use {} as {};", self.source.print(cache, tcx), name)
                 }
             }
             clean::ImportKind::Glob => {
                 if self.source.path.segments.is_empty() {
                     write!(f, "use *;")
                 } else {
-                    write!(f, "use {}::*;", self.source.print(cache))
+                    write!(f, "use {}::*;", self.source.print(cache, tcx))
                 }
             }
         })
@@ -1223,9 +1302,13 @@ impl clean::Import {
 }
 
 impl clean::ImportSource {
-    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
+    crate fn print<'b, 'a: 'b, 'tcx: 'a>(
+        &'a self,
+        cache: &'b Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'b + Captures<'tcx> {
         display_fn(move |f| match self.did {
-            Some(did) => resolved_path(f, did, &self.path, true, false, cache),
+            Some(did) => resolved_path(f, did, &self.path, true, false, cache, tcx),
             _ => {
                 for seg in &self.path.segments[..self.path.segments.len() - 1] {
                     write!(f, "{}::", seg.name)?;
@@ -1243,23 +1326,27 @@ impl clean::ImportSource {
 }
 
 impl clean::TypeBinding {
-    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
+    crate fn print<'b, 'a: 'b, 'tcx: 'a>(
+        &'a self,
+        cache: &'b Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'b + Captures<'tcx> {
         display_fn(move |f| {
             f.write_str(&*self.name.as_str())?;
             match self.kind {
                 clean::TypeBindingKind::Equality { ref ty } => {
                     if f.alternate() {
-                        write!(f, " = {:#}", ty.print(cache))?;
+                        write!(f, " = {:#}", ty.print(cache, tcx))?;
                     } else {
-                        write!(f, " = {}", ty.print(cache))?;
+                        write!(f, " = {}", ty.print(cache, tcx))?;
                     }
                 }
                 clean::TypeBindingKind::Constraint { ref bounds } => {
                     if !bounds.is_empty() {
                         if f.alternate() {
-                            write!(f, ": {:#}", print_generic_bounds(bounds, cache))?;
+                            write!(f, ": {:#}", print_generic_bounds(bounds, cache, tcx))?;
                         } else {
-                            write!(f, ":&nbsp;{}", print_generic_bounds(bounds, cache))?;
+                            write!(f, ":&nbsp;{}", print_generic_bounds(bounds, cache, tcx))?;
                         }
                     }
                 }
@@ -1284,11 +1371,15 @@ crate fn print_default_space<'a>(v: bool) -> &'a str {
 }
 
 impl clean::GenericArg {
-    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
+    crate fn print<'b, 'a: 'b, 'tcx: 'a>(
+        &'a self,
+        cache: &'b Cache,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl fmt::Display + 'b + Captures<'tcx> {
         display_fn(move |f| match self {
             clean::GenericArg::Lifetime(lt) => fmt::Display::fmt(&lt.print(), f),
-            clean::GenericArg::Type(ty) => fmt::Display::fmt(&ty.print(cache), f),
-            clean::GenericArg::Const(ct) => fmt::Display::fmt(&ct.print(), f),
+            clean::GenericArg::Type(ty) => fmt::Display::fmt(&ty.print(cache, tcx), f),
+            clean::GenericArg::Const(ct) => fmt::Display::fmt(&ct.print(tcx), f),
         })
     }
 }
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index b39f9f87892..cdccb1c8581 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1162,6 +1162,7 @@ crate fn plain_text_summary(md: &str) -> String {
     s
 }
 
+#[derive(Debug)]
 crate struct MarkdownLink {
     pub kind: LinkType,
     pub link: String,
@@ -1354,6 +1355,7 @@ fn init_id_map() -> FxHashMap<String, usize> {
     map.insert("default-settings".to_owned(), 1);
     map.insert("rustdoc-vars".to_owned(), 1);
     map.insert("sidebar-vars".to_owned(), 1);
+    map.insert("copy-path".to_owned(), 1);
     // This is the list of IDs used by rustdoc sections.
     map.insert("fields".to_owned(), 1);
     map.insert("variants".to_owned(), 1);
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 17cedeb5a51..07c850a20a9 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -279,6 +279,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         "html"
     }
 
+    const RUN_ON_MODULE: bool = true;
+
     fn init(
         mut krate: clean::Crate,
         options: RenderOptions,
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 05d30187aa8..07bd26a4c5e 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -67,8 +67,8 @@ use crate::formats::item_type::ItemType;
 use crate::formats::{AssocItemRender, FormatRenderer, Impl, RenderMode};
 use crate::html::escape::Escape;
 use crate::html::format::{
-    href, print_abi_with_space, print_default_space, print_generic_bounds, Buffer, Function,
-    PrintWithSpace, WhereClause,
+    href, print_abi_with_space, print_default_space, print_generic_bounds, print_where_clause,
+    Buffer, PrintWithSpace,
 };
 use crate::html::layout;
 use crate::html::markdown::{self, ErrorCodes, Markdown, MarkdownHtml, MarkdownSummaryLine};
@@ -855,10 +855,12 @@ fn render_impls(
     traits: &[&&Impl],
     containing_item: &clean::Item,
 ) {
+    let cache = cx.cache();
+    let tcx = cx.tcx();
     let mut impls = traits
         .iter()
         .map(|i| {
-            let did = i.trait_did_full(cx.cache()).unwrap();
+            let did = i.trait_did_full(cache).unwrap();
             let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods);
             let mut buffer = if w.is_for_html() { Buffer::html() } else { Buffer::new() };
             render_impl(
@@ -868,8 +870,8 @@ fn render_impls(
                 containing_item,
                 assoc_link,
                 RenderMode::Normal,
-                containing_item.stable_since(cx.tcx()).as_deref(),
-                containing_item.const_stable_since(cx.tcx()).as_deref(),
+                containing_item.stable_since(tcx).as_deref(),
+                containing_item.const_stable_since(tcx).as_deref(),
                 true,
                 None,
                 false,
@@ -911,14 +913,16 @@ fn assoc_const(
     extra: &str,
     cx: &Context<'_>,
 ) {
+    let cache = cx.cache();
+    let tcx = cx.tcx();
     write!(
         w,
         "{}{}const <a href=\"{}\" class=\"constant\"><b>{}</b></a>: {}",
         extra,
-        it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
-        naive_assoc_href(it, link, cx.cache()),
+        it.visibility.print_with_space(tcx, it.def_id, cache),
+        naive_assoc_href(it, link, cache),
         it.name.as_ref().unwrap(),
-        ty.print(cx.cache())
+        ty.print(cache, tcx)
     );
 }
 
@@ -930,6 +934,7 @@ fn assoc_type(
     link: AssocItemLink<'_>,
     extra: &str,
     cache: &Cache,
+    tcx: TyCtxt<'_>,
 ) {
     write!(
         w,
@@ -939,10 +944,10 @@ fn assoc_type(
         it.name.as_ref().unwrap()
     );
     if !bounds.is_empty() {
-        write!(w, ": {}", print_generic_bounds(bounds, cache))
+        write!(w, ": {}", print_generic_bounds(bounds, cache, tcx))
     }
     if let Some(default) = default {
-        write!(w, " = {}", default.print(cache))
+        write!(w, " = {}", default.print(cache, tcx))
     }
 }
 
@@ -992,6 +997,8 @@ fn render_assoc_item(
         parent: ItemType,
         cx: &Context<'_>,
     ) {
+        let cache = cx.cache();
+        let tcx = cx.tcx();
         let name = meth.name.as_ref().unwrap();
         let anchor = format!("#{}.{}", meth.type_(), name);
         let href = match link {
@@ -1006,18 +1013,17 @@ fn render_assoc_item(
                     ItemType::TyMethod
                 };
 
-                href(did, cx.cache()).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor)
+                href(did, cache).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor)
             }
         };
-        let tcx = cx.tcx();
-        let vis = meth.visibility.print_with_space(tcx, meth.def_id, cx.cache()).to_string();
+        let vis = meth.visibility.print_with_space(tcx, meth.def_id, cache).to_string();
         let constness = header.constness.print_with_space();
         let asyncness = header.asyncness.print_with_space();
         let unsafety = header.unsafety.print_with_space();
         let defaultness = print_default_space(meth.is_default());
         let abi = print_abi_with_space(header.abi).to_string();
         // NOTE: `{:#}` does not print HTML formatting, `{}` does. So `g.print` can't be reused between the length calculation and `write!`.
-        let generics_len = format!("{:#}", g.print(cx.cache())).len();
+        let generics_len = format!("{:#}", g.print(cache, tcx)).len();
         let mut header_len = "fn ".len()
             + vis.len()
             + constness.len()
@@ -1049,11 +1055,10 @@ fn render_assoc_item(
             abi,
             href = href,
             name = name,
-            generics = g.print(cx.cache()),
-            decl = Function { decl: d, header_len, indent, asyncness: header.asyncness }
-                .print(cx.cache()),
-            spotlight = spotlight_decl(&d, cx.cache()),
-            where_clause = WhereClause { gens: g, indent, end_newline }.print(cx.cache())
+            generics = g.print(cache, tcx),
+            decl = d.full_print(cache, tcx, header_len, indent, header.asyncness),
+            spotlight = spotlight_decl(&d, cache, tcx),
+            where_clause = print_where_clause(g, cache, tcx, indent, end_newline),
         )
     }
     match *item.kind {
@@ -1081,6 +1086,7 @@ fn render_assoc_item(
             link,
             if parent == ItemType::Trait { "    " } else { "" },
             cx.cache(),
+            cx.tcx(),
         ),
         _ => panic!("render_assoc_item called on non-associated-item"),
     }
@@ -1155,6 +1161,8 @@ fn render_assoc_items(
         Some(v) => v,
         None => return,
     };
+    let tcx = cx.tcx();
+    let cache = cx.cache();
     let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
     if !non_trait.is_empty() {
         let render_mode = match what {
@@ -1169,12 +1177,10 @@ fn render_assoc_items(
             AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
                 let id = cx.derive_id(small_url_encode(format!(
                     "deref-methods-{:#}",
-                    type_.print(cx.cache())
+                    type_.print(cache, tcx)
                 )));
-                debug!("Adding {} to deref id map", type_.print(cx.cache()));
-                cx.deref_id_map
-                    .borrow_mut()
-                    .insert(type_.def_id_full(cx.cache()).unwrap(), id.clone());
+                debug!("Adding {} to deref id map", type_.print(cache, tcx));
+                cx.deref_id_map.borrow_mut().insert(type_.def_id_full(cache).unwrap(), id.clone());
                 write!(
                     w,
                     "<h2 id=\"{id}\" class=\"small-section-header\">\
@@ -1182,8 +1188,8 @@ fn render_assoc_items(
                          <a href=\"#{id}\" class=\"anchor\"></a>\
                      </h2>",
                     id = id,
-                    trait_ = trait_.print(cx.cache()),
-                    type_ = type_.print(cx.cache()),
+                    trait_ = trait_.print(cache, tcx),
+                    type_ = type_.print(cache, tcx),
                 );
                 RenderMode::ForDeref { mut_: deref_mut_ }
             }
@@ -1196,8 +1202,8 @@ fn render_assoc_items(
                 containing_item,
                 AssocItemLink::Anchor(None),
                 render_mode,
-                containing_item.stable_since(cx.tcx()).as_deref(),
-                containing_item.const_stable_since(cx.tcx()).as_deref(),
+                containing_item.stable_since(tcx).as_deref(),
+                containing_item.const_stable_since(tcx).as_deref(),
                 true,
                 None,
                 false,
@@ -1209,11 +1215,11 @@ fn render_assoc_items(
     if !traits.is_empty() {
         let deref_impl = traits
             .iter()
-            .find(|t| t.inner_impl().trait_.def_id_full(cx.cache()) == cx.cache.deref_trait_did);
+            .find(|t| t.inner_impl().trait_.def_id_full(cache) == cx.cache.deref_trait_did);
         if let Some(impl_) = deref_impl {
-            let has_deref_mut = traits.iter().any(|t| {
-                t.inner_impl().trait_.def_id_full(cx.cache()) == cx.cache.deref_mut_trait_did
-            });
+            let has_deref_mut = traits
+                .iter()
+                .any(|t| t.inner_impl().trait_.def_id_full(cache) == cx.cache.deref_mut_trait_did);
             render_deref_methods(w, cx, impl_, containing_item, has_deref_mut);
         }
 
@@ -1335,7 +1341,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, cache: &Cache) -> bo
     }
 }
 
-fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache) -> String {
+fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache, tcx: TyCtxt<'_>) -> String {
     let mut out = Buffer::html();
     let mut trait_ = String::new();
 
@@ -1351,16 +1357,16 @@ fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache) -> String {
                             &mut out,
                             "<h3 class=\"notable\">Notable traits for {}</h3>\
                              <code class=\"content\">",
-                            impl_.for_.print(cache)
+                            impl_.for_.print(cache, tcx)
                         );
-                        trait_.push_str(&impl_.for_.print(cache).to_string());
+                        trait_.push_str(&impl_.for_.print(cache, tcx).to_string());
                     }
 
                     //use the "where" class here to make it small
                     write!(
                         &mut out,
                         "<span class=\"where fmt-newline\">{}</span>",
-                        impl_.print(cache, false)
+                        impl_.print(cache, false, tcx)
                     );
                     let t_did = impl_.trait_.def_id_full(cache).unwrap();
                     for it in &impl_.items {
@@ -1374,6 +1380,7 @@ fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache) -> String {
                                 AssocItemLink::GotoSource(t_did, &FxHashSet::default()),
                                 "",
                                 cache,
+                                tcx,
                             );
                             out.push_str(";</span>");
                         }
@@ -1413,15 +1420,17 @@ fn render_impl(
     aliases: &[String],
 ) {
     let traits = &cx.cache.traits;
-    let trait_ = i.trait_did_full(cx.cache()).map(|did| &traits[&did]);
+    let tcx = cx.tcx();
+    let cache = cx.cache();
+    let trait_ = i.trait_did_full(cache).map(|did| &traits[&did]);
 
     if render_mode == RenderMode::Normal {
         let id = cx.derive_id(match i.inner_impl().trait_ {
             Some(ref t) => {
                 if is_on_foreign_type {
-                    get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cx.cache())
+                    get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cache, tcx)
                 } else {
-                    format!("impl-{}", small_url_encode(format!("{:#}", t.print(cx.cache()))))
+                    format!("impl-{}", small_url_encode(format!("{:#}", t.print(cache, tcx))))
                 }
             }
             None => "impl".to_string(),
@@ -1433,7 +1442,7 @@ fn render_impl(
         };
         if let Some(use_absolute) = use_absolute {
             write!(w, "<h3 id=\"{}\" class=\"impl\"{}><code class=\"in-band\">", id, aliases);
-            write!(w, "{}", i.inner_impl().print(cx.cache(), use_absolute));
+            write!(w, "{}", i.inner_impl().print(cache, use_absolute, tcx));
             if show_def_docs {
                 for it in &i.inner_impl().items {
                     if let clean::TypedefItem(ref tydef, _) = *it.kind {
@@ -1445,7 +1454,8 @@ fn render_impl(
                             Some(&tydef.type_),
                             AssocItemLink::Anchor(None),
                             "",
-                            cx.cache(),
+                            cache,
+                            tcx,
                         );
                         w.write_str(";</span>");
                     }
@@ -1458,14 +1468,14 @@ fn render_impl(
                 "<h3 id=\"{}\" class=\"impl\"{}><code class=\"in-band\">{}</code>",
                 id,
                 aliases,
-                i.inner_impl().print(cx.cache(), false)
+                i.inner_impl().print(cache, false, tcx)
             );
         }
         write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
         render_stability_since_raw(
             w,
-            i.impl_item.stable_since(cx.tcx()).as_deref(),
-            i.impl_item.const_stable_since(cx.tcx()).as_deref(),
+            i.impl_item.stable_since(tcx).as_deref(),
+            i.impl_item.const_stable_since(tcx).as_deref(),
             outer_version,
             outer_const_version,
         );
@@ -1511,6 +1521,7 @@ fn render_impl(
     ) {
         let item_type = item.type_();
         let name = item.name.as_ref().unwrap();
+        let tcx = cx.tcx();
 
         let render_method_item = match render_mode {
             RenderMode::Normal => true,
@@ -1538,8 +1549,8 @@ fn render_impl(
                     w.write_str("</code>");
                     render_stability_since_raw(
                         w,
-                        item.stable_since(cx.tcx()).as_deref(),
-                        item.const_stable_since(cx.tcx()).as_deref(),
+                        item.stable_since(tcx).as_deref(),
+                        item.const_stable_since(tcx).as_deref(),
                         outer_version,
                         outer_const_version,
                     );
@@ -1558,6 +1569,7 @@ fn render_impl(
                     link.anchor(&id),
                     "",
                     cx.cache(),
+                    tcx,
                 );
                 w.write_str("</code></h4>");
             }
@@ -1568,8 +1580,8 @@ fn render_impl(
                 w.write_str("</code>");
                 render_stability_since_raw(
                     w,
-                    item.stable_since(cx.tcx()).as_deref(),
-                    item.const_stable_since(cx.tcx()).as_deref(),
+                    item.stable_since(tcx).as_deref(),
+                    item.const_stable_since(tcx).as_deref(),
                     outer_version,
                     outer_const_version,
                 );
@@ -1579,7 +1591,16 @@ fn render_impl(
             clean::AssocTypeItem(ref bounds, ref default) => {
                 let id = cx.derive_id(format!("{}.{}", item_type, name));
                 write!(w, "<h4 id=\"{}\" class=\"{}{}\"><code>", id, item_type, extra_class);
-                assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id), "", cx.cache());
+                assoc_type(
+                    w,
+                    item,
+                    bounds,
+                    default.as_ref(),
+                    link.anchor(&id),
+                    "",
+                    cx.cache(),
+                    tcx,
+                );
                 w.write_str("</code></h4>");
             }
             clean::StrippedItem(..) => return,
@@ -1882,6 +1903,8 @@ fn small_url_encode(s: String) -> String {
 fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
     if let Some(v) = cx.cache.impls.get(&it.def_id) {
         let mut used_links = FxHashSet::default();
+        let tcx = cx.tcx();
+        let cache = cx.cache();
 
         {
             let used_links_bor = &mut used_links;
@@ -1911,7 +1934,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
             if let Some(impl_) = v
                 .iter()
                 .filter(|i| i.inner_impl().trait_.is_some())
-                .find(|i| i.inner_impl().trait_.def_id_full(cx.cache()) == cx.cache.deref_trait_did)
+                .find(|i| i.inner_impl().trait_.def_id_full(cache) == cx.cache.deref_trait_did)
             {
                 sidebar_deref_methods(cx, out, impl_, v);
             }
@@ -1922,9 +1945,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
                     .iter()
                     .filter_map(|it| {
                         if let Some(ref i) = it.inner_impl().trait_ {
-                            let i_display = format!("{:#}", i.print(cx.cache()));
+                            let i_display = format!("{:#}", i.print(cache, tcx));
                             let out = Escape(&i_display);
-                            let encoded = small_url_encode(format!("{:#}", i.print(cx.cache())));
+                            let encoded = small_url_encode(format!("{:#}", i.print(cache, tcx)));
                             let generated = format!(
                                 "<a href=\"#impl-{}\">{}{}</a>",
                                 encoded,
@@ -1988,6 +2011,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
 
 fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &Vec<Impl>) {
     let c = cx.cache();
+    let tcx = cx.tcx();
 
     debug!("found Deref: {:?}", impl_);
     if let Some((target, real_target)) =
@@ -2000,8 +2024,8 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
         })
     {
         debug!("found target, real_target: {:?} {:?}", target, real_target);
-        if let Some(did) = target.def_id_full(cx.cache()) {
-            if let Some(type_did) = impl_.inner_impl().for_.def_id_full(cx.cache()) {
+        if let Some(did) = target.def_id_full(c) {
+            if let Some(type_did) = impl_.inner_impl().for_.def_id_full(c) {
                 // `impl Deref<Target = S> for S`
                 if did == type_did {
                     // Avoid infinite cycles
@@ -2012,9 +2036,9 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
         let deref_mut = v
             .iter()
             .filter(|i| i.inner_impl().trait_.is_some())
-            .any(|i| i.inner_impl().trait_.def_id_full(cx.cache()) == c.deref_mut_trait_did);
+            .any(|i| i.inner_impl().trait_.def_id_full(c) == c.deref_mut_trait_did);
         let inner_impl = target
-            .def_id_full(cx.cache())
+            .def_id_full(c)
             .or_else(|| {
                 target.primitive_type().and_then(|prim| c.primitive_locations.get(&prim).cloned())
             })
@@ -2030,14 +2054,17 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
             if !ret.is_empty() {
                 let deref_id_map = cx.deref_id_map.borrow();
                 let id = deref_id_map
-                    .get(&real_target.def_id_full(cx.cache()).unwrap())
+                    .get(&real_target.def_id_full(c).unwrap())
                     .expect("Deref section without derived id");
                 write!(
                     out,
                     "<a class=\"sidebar-title\" href=\"#{}\">Methods from {}&lt;Target={}&gt;</a>",
                     id,
-                    Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print(c))),
-                    Escape(&format!("{:#}", real_target.print(c))),
+                    Escape(&format!(
+                        "{:#}",
+                        impl_.inner_impl().trait_.as_ref().unwrap().print(c, tcx)
+                    )),
+                    Escape(&format!("{:#}", real_target.print(c, tcx))),
                 );
                 // We want links' order to be reproducible so we don't use unstable sort.
                 ret.sort();
@@ -2050,12 +2077,12 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
         }
 
         // Recurse into any further impls that might exist for `target`
-        if let Some(target_did) = target.def_id_full(cx.cache()) {
+        if let Some(target_did) = target.def_id_full(c) {
             if let Some(target_impls) = c.impls.get(&target_did) {
                 if let Some(target_deref_impl) = target_impls
                     .iter()
                     .filter(|i| i.inner_impl().trait_.is_some())
-                    .find(|i| i.inner_impl().trait_.def_id_full(cx.cache()) == c.deref_trait_did)
+                    .find(|i| i.inner_impl().trait_.def_id_full(c) == c.deref_trait_did)
                 {
                     sidebar_deref_methods(cx, out, target_deref_impl, target_impls);
                 }
@@ -2094,17 +2121,26 @@ fn get_id_for_impl_on_foreign_type(
     for_: &clean::Type,
     trait_: &clean::Type,
     cache: &Cache,
+    tcx: TyCtxt<'_>,
 ) -> String {
-    small_url_encode(format!("impl-{:#}-for-{:#}", trait_.print(cache), for_.print(cache)))
+    small_url_encode(format!(
+        "impl-{:#}-for-{:#}",
+        trait_.print(cache, tcx),
+        for_.print(cache, tcx)
+    ))
 }
 
-fn extract_for_impl_name(item: &clean::Item, cache: &Cache) -> Option<(String, String)> {
+fn extract_for_impl_name(
+    item: &clean::Item,
+    cache: &Cache,
+    tcx: TyCtxt<'_>,
+) -> Option<(String, String)> {
     match *item.kind {
         clean::ItemKind::ImplItem(ref i) => {
             if let Some(ref trait_) = i.trait_ {
                 Some((
-                    format!("{:#}", i.for_.print(cache)),
-                    get_id_for_impl_on_foreign_type(&i.for_, trait_, cache),
+                    format!("{:#}", i.for_.print(cache, tcx)),
+                    get_id_for_impl_on_foreign_type(&i.for_, trait_, cache, tcx),
                 ))
             } else {
                 None
@@ -2184,15 +2220,17 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
     );
 
     if let Some(implementors) = cx.cache.implementors.get(&it.def_id) {
+        let cache = cx.cache();
+        let tcx = cx.tcx();
         let mut res = implementors
             .iter()
             .filter(|i| {
                 i.inner_impl()
                     .for_
-                    .def_id_full(cx.cache())
+                    .def_id_full(cache)
                     .map_or(false, |d| !cx.cache.paths.contains_key(&d))
             })
-            .filter_map(|i| extract_for_impl_name(&i.impl_item, cx.cache()))
+            .filter_map(|i| extract_for_impl_name(&i.impl_item, cache, tcx))
             .collect::<Vec<_>>();
 
         if !res.is_empty() {
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index c3c4c4952b3..25314f87eb5 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -19,7 +19,7 @@ use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
 use crate::formats::{AssocItemRender, FormatRenderer, Impl, RenderMode};
 use crate::html::escape::Escape;
-use crate::html::format::{print_abi_with_space, Buffer, Function, PrintWithSpace, WhereClause};
+use crate::html::format::{print_abi_with_space, print_where_clause, Buffer, PrintWithSpace};
 use crate::html::highlight;
 use crate::html::markdown::MarkdownSummaryLine;
 
@@ -73,6 +73,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer)
         }
     }
     write!(buf, "<a class=\"{}\" href=\"\">{}</a>", item.type_(), item.name.as_ref().unwrap());
+    write!(buf, "<button id=\"copy-path\" onclick=\"copy_path(this)\">⎘</button>");
 
     buf.write_str("</span>"); // in-band
     buf.write_str("<span class=\"out-of-band\">");
@@ -266,7 +267,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
                     w,
                     "<tr><td><code>{}{}</code></td></tr>",
                     myitem.visibility.print_with_space(cx.tcx(), myitem.def_id, cx.cache()),
-                    import.print(cx.cache())
+                    import.print(cx.cache(), cx.tcx()),
                 );
             }
 
@@ -372,7 +373,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
         f.header.unsafety.print_with_space(),
         print_abi_with_space(f.header.abi),
         it.name.as_ref().unwrap(),
-        f.generics.print(cx.cache())
+        f.generics.print(cx.cache(), cx.tcx())
     )
     .len();
     w.write_str("<pre class=\"rust fn\">");
@@ -387,18 +388,16 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
         unsafety = f.header.unsafety.print_with_space(),
         abi = print_abi_with_space(f.header.abi),
         name = it.name.as_ref().unwrap(),
-        generics = f.generics.print(cx.cache()),
-        where_clause =
-            WhereClause { gens: &f.generics, indent: 0, end_newline: true }.print(cx.cache()),
-        decl = Function { decl: &f.decl, header_len, indent: 0, asyncness: f.header.asyncness }
-            .print(cx.cache()),
-        spotlight = spotlight_decl(&f.decl, cx.cache()),
+        generics = f.generics.print(cx.cache(), cx.tcx()),
+        where_clause = print_where_clause(&f.generics, cx.cache(), cx.tcx(), 0, true),
+        decl = f.decl.full_print(cx.cache(), cx.tcx(), header_len, 0, f.header.asyncness),
+        spotlight = spotlight_decl(&f.decl, cx.cache(), cx.tcx()),
     );
     document(w, cx, it, None)
 }
 
 fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) {
-    let bounds = bounds(&t.bounds, false, cx.cache());
+    let bounds = bounds(&t.bounds, false, cx.cache(), cx.tcx());
     let types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
     let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::<Vec<_>>();
     let required = t.items.iter().filter(|m| m.is_ty_method()).collect::<Vec<_>>();
@@ -415,13 +414,12 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
             t.unsafety.print_with_space(),
             if t.is_auto { "auto " } else { "" },
             it.name.as_ref().unwrap(),
-            t.generics.print(cx.cache()),
+            t.generics.print(cx.cache(), cx.tcx()),
             bounds
         );
 
         if !t.generics.where_predicates.is_empty() {
-            let where_ = WhereClause { gens: &t.generics, indent: 0, end_newline: true };
-            write!(w, "{}", where_.print(cx.cache()));
+            write!(w, "{}", print_where_clause(&t.generics, cx.cache(), cx.tcx(), 0, true));
         } else {
             w.write_str(" ");
         }
@@ -594,8 +592,8 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
         let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
             local.iter().partition(|i| i.inner_impl().synthetic);
 
-        synthetic.sort_by(|a, b| compare_impl(a, b, cx.cache()));
-        concrete.sort_by(|a, b| compare_impl(a, b, cx.cache()));
+        synthetic.sort_by(|a, b| compare_impl(a, b, cx.cache(), cx.tcx()));
+        concrete.sort_by(|a, b| compare_impl(a, b, cx.cache(), cx.tcx()));
 
         if !foreign.is_empty() {
             write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "");
@@ -700,9 +698,9 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
         w,
         "trait {}{}{} = {};</pre>",
         it.name.as_ref().unwrap(),
-        t.generics.print(cx.cache()),
-        WhereClause { gens: &t.generics, indent: 0, end_newline: true }.print(cx.cache()),
-        bounds(&t.bounds, true, cx.cache())
+        t.generics.print(cx.cache(), cx.tcx()),
+        print_where_clause(&t.generics, cx.cache(), cx.tcx(), 0, true),
+        bounds(&t.bounds, true, cx.cache(), cx.tcx())
     );
 
     document(w, cx, it, None);
@@ -721,10 +719,9 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
         w,
         "type {}{}{where_clause} = impl {bounds};</pre>",
         it.name.as_ref().unwrap(),
-        t.generics.print(cx.cache()),
-        where_clause =
-            WhereClause { gens: &t.generics, indent: 0, end_newline: true }.print(cx.cache()),
-        bounds = bounds(&t.bounds, false, cx.cache())
+        t.generics.print(cx.cache(), cx.tcx()),
+        where_clause = print_where_clause(&t.generics, cx.cache(), cx.tcx(), 0, true),
+        bounds = bounds(&t.bounds, false, cx.cache(), cx.tcx()),
     );
 
     document(w, cx, it, None);
@@ -743,10 +740,9 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T
         w,
         "type {}{}{where_clause} = {type_};</pre>",
         it.name.as_ref().unwrap(),
-        t.generics.print(cx.cache()),
-        where_clause =
-            WhereClause { gens: &t.generics, indent: 0, end_newline: true }.print(cx.cache()),
-        type_ = t.type_.print(cx.cache())
+        t.generics.print(cx.cache(), cx.tcx()),
+        where_clause = print_where_clause(&t.generics, cx.cache(), cx.tcx(), 0, true),
+        type_ = t.type_.print(cx.cache(), cx.tcx()),
     );
 
     document(w, cx, it, None);
@@ -793,7 +789,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
                 id = id,
                 name = name,
                 shortty = ItemType::StructField,
-                ty = ty.print(cx.cache())
+                ty = ty.print(cx.cache(), cx.tcx()),
             );
             if let Some(stability_class) = field.stability_class(cx.tcx()) {
                 write!(w, "<span class=\"stab {stab}\"></span>", stab = stability_class);
@@ -813,8 +809,8 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
             "{}enum {}{}{}",
             it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
             it.name.as_ref().unwrap(),
-            e.generics.print(cx.cache()),
-            WhereClause { gens: &e.generics, indent: 0, end_newline: true }.print(cx.cache())
+            e.generics.print(cx.cache(), cx.tcx()),
+            print_where_clause(&e.generics, cx.cache(), cx.tcx(), 0, true),
         );
         if e.variants.is_empty() && !e.variants_stripped {
             w.write_str(" {}");
@@ -832,7 +828,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                                 if i > 0 {
                                     w.write_str(",&nbsp;")
                                 }
-                                write!(w, "{}", ty.print(cx.cache()));
+                                write!(w, "{}", ty.print(cx.cache(), cx.tcx()));
                             }
                             w.write_str(")");
                         }
@@ -879,7 +875,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                     if i > 0 {
                         w.write_str(",&nbsp;");
                     }
-                    write!(w, "{}", ty.print(cx.cache()));
+                    write!(w, "{}", ty.print(cx.cache(), cx.tcx()));
                 }
                 w.write_str(")");
             }
@@ -916,7 +912,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                              </span>",
                             id = id,
                             f = field.name.as_ref().unwrap(),
-                            t = ty.print(cx.cache())
+                            t = ty.print(cx.cache(), cx.tcx())
                         );
                         document(w, cx, field, Some(variant));
                     }
@@ -987,19 +983,22 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::
         "{vis}const {name}: {typ}",
         vis = it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
         name = it.name.as_ref().unwrap(),
-        typ = c.type_.print(cx.cache()),
+        typ = c.type_.print(cx.cache(), cx.tcx()),
     );
 
-    if c.value.is_some() || c.is_literal {
-        write!(w, " = {expr};", expr = Escape(&c.expr));
+    let value = c.value(cx.tcx());
+    let is_literal = c.is_literal(cx.tcx());
+    let expr = c.expr(cx.tcx());
+    if value.is_some() || is_literal {
+        write!(w, " = {expr};", expr = Escape(&expr));
     } else {
         w.write_str(";");
     }
 
-    if let Some(value) = &c.value {
-        if !c.is_literal {
+    if !is_literal {
+        if let Some(value) = &value {
             let value_lowercase = value.to_lowercase();
-            let expr_lowercase = c.expr.to_lowercase();
+            let expr_lowercase = expr.to_lowercase();
 
             if value_lowercase != expr_lowercase
                 && value_lowercase.trim_end_matches("i32") != expr_lowercase
@@ -1054,7 +1053,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
                     item_type = ItemType::StructField,
                     id = id,
                     name = field.name.as_ref().unwrap(),
-                    ty = ty.print(cx.cache())
+                    ty = ty.print(cx.cache(), cx.tcx())
                 );
                 document(w, cx, field, Some(it));
             }
@@ -1072,7 +1071,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
         vis = it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
         mutability = s.mutability.print_with_space(),
         name = it.name.as_ref().unwrap(),
-        typ = s.type_.print(cx.cache())
+        typ = s.type_.print(cx.cache(), cx.tcx())
     );
     document(w, cx, it, None)
 }
@@ -1147,7 +1146,12 @@ pub(super) fn item_path(ty: ItemType, name: &str) -> String {
     }
 }
 
-fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool, cache: &Cache) -> String {
+fn bounds(
+    t_bounds: &[clean::GenericBound],
+    trait_alias: bool,
+    cache: &Cache,
+    tcx: TyCtxt<'_>,
+) -> String {
     let mut bounds = String::new();
     if !t_bounds.is_empty() {
         if !trait_alias {
@@ -1157,7 +1161,7 @@ fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool, cache: &Cache) ->
             if i > 0 {
                 bounds.push_str(" + ");
             }
-            bounds.push_str(&p.print(cache).to_string());
+            bounds.push_str(&p.print(cache, tcx).to_string());
         }
     }
     bounds
@@ -1187,9 +1191,14 @@ fn render_stability_since(
     )
 }
 
-fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl, cache: &Cache) -> Ordering {
-    let lhs = format!("{}", lhs.inner_impl().print(cache, false));
-    let rhs = format!("{}", rhs.inner_impl().print(cache, false));
+fn compare_impl<'a, 'b>(
+    lhs: &'a &&Impl,
+    rhs: &'b &&Impl,
+    cache: &Cache,
+    tcx: TyCtxt<'_>,
+) -> Ordering {
+    let lhs = format!("{}", lhs.inner_impl().print(cache, false, tcx));
+    let rhs = format!("{}", rhs.inner_impl().print(cache, false, tcx));
 
     // lhs and rhs are formatted as HTML, which may be unnecessary
     compare_names(&lhs, &rhs)
@@ -1247,8 +1256,8 @@ fn render_union(
         it.name.as_ref().unwrap()
     );
     if let Some(g) = g {
-        write!(w, "{}", g.print(cx.cache()));
-        write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: true }.print(cx.cache()));
+        write!(w, "{}", g.print(cx.cache(), cx.tcx()));
+        write!(w, "{}", print_where_clause(&g, cx.cache(), cx.tcx(), 0, true));
     }
 
     write!(w, " {{\n{}", tab);
@@ -1259,7 +1268,7 @@ fn render_union(
                 "    {}{}: {},\n{}",
                 field.visibility.print_with_space(cx.tcx(), field.def_id, cx.cache()),
                 field.name.as_ref().unwrap(),
-                ty.print(cx.cache()),
+                ty.print(cx.cache(), cx.tcx()),
                 tab
             );
         }
@@ -1289,16 +1298,12 @@ fn render_struct(
         it.name.as_ref().unwrap()
     );
     if let Some(g) = g {
-        write!(w, "{}", g.print(cx.cache()))
+        write!(w, "{}", g.print(cx.cache(), cx.tcx()))
     }
     match ty {
         CtorKind::Fictive => {
             if let Some(g) = g {
-                write!(
-                    w,
-                    "{}",
-                    WhereClause { gens: g, indent: 0, end_newline: true }.print(cx.cache())
-                )
+                write!(w, "{}", print_where_clause(g, cx.cache(), cx.tcx(), 0, true),)
             }
             let mut has_visible_fields = false;
             w.write_str(" {");
@@ -1310,7 +1315,7 @@ fn render_struct(
                         tab,
                         field.visibility.print_with_space(cx.tcx(), field.def_id, cx.cache()),
                         field.name.as_ref().unwrap(),
-                        ty.print(cx.cache())
+                        ty.print(cx.cache(), cx.tcx()),
                     );
                     has_visible_fields = true;
                 }
@@ -1341,7 +1346,7 @@ fn render_struct(
                             w,
                             "{}{}",
                             field.visibility.print_with_space(cx.tcx(), field.def_id, cx.cache()),
-                            ty.print(cx.cache())
+                            ty.print(cx.cache(), cx.tcx()),
                         )
                     }
                     _ => unreachable!(),
@@ -1349,22 +1354,14 @@ fn render_struct(
             }
             w.write_str(")");
             if let Some(g) = g {
-                write!(
-                    w,
-                    "{}",
-                    WhereClause { gens: g, indent: 0, end_newline: false }.print(cx.cache())
-                )
+                write!(w, "{}", print_where_clause(g, cx.cache(), cx.tcx(), 0, false),)
             }
             w.write_str(";");
         }
         CtorKind::Const => {
             // Needed for PhantomData.
             if let Some(g) = g {
-                write!(
-                    w,
-                    "{}",
-                    WhereClause { gens: g, indent: 0, end_newline: false }.print(cx.cache())
-                )
+                write!(w, "{}", print_where_clause(g, cx.cache(), cx.tcx(), 0, false),)
             }
             w.write_str(";");
         }
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index b2f2283c177..59dc4ef9449 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -500,7 +500,7 @@ pub(super) fn write_shared(
                     None
                 } else {
                     Some(Implementor {
-                        text: imp.inner_impl().print(cx.cache(), false).to_string(),
+                        text: imp.inner_impl().print(cx.cache(), false, cx.tcx()).to_string(),
                         synthetic: imp.inner_impl().synthetic,
                         types: collect_paths_for_type(imp.inner_impl().for_.clone(), cx.cache()),
                     })
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 1b6a82fed11..001c8b09044 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -54,12 +54,10 @@ impl DocFolder for SourceCollector<'_, '_> {
             self.scx.include_sources = match self.emit_source(&filename) {
                 Ok(()) => true,
                 Err(e) => {
-                    println!(
-                        "warning: source code was requested to be rendered, \
-                         but processing `{}` had an error: {}",
-                        filename, e
+                    self.scx.tcx.sess.span_err(
+                        item.span.inner(),
+                        &format!("failed to render source code for `{}`: {}", filename, e),
                     );
-                    println!("         skipping rendering of source code");
                     false
                 }
             };
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index da2952bbebd..f2e62ee7b6b 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -3061,3 +3061,28 @@ function hideThemeButtonState() {
     window.onhashchange = onHashChange;
     setupSearchLoader();
 }());
+
+function copy_path(but) {
+    var parent = but.parentElement;
+    var path = [];
+
+    onEach(parent.childNodes, function(child) {
+        if (child.tagName === 'A') {
+            path.push(child.textContent);
+        }
+    });
+
+    var el = document.createElement('textarea');
+    el.value = 'use ' + path.join('::') + ';';
+    el.setAttribute('readonly', '');
+    // To not make it appear on the screen.
+    el.style.position = 'absolute';
+    el.style.left = '-9999px';
+
+    document.body.appendChild(el);
+    el.select();
+    document.execCommand('copy');
+    document.body.removeChild(el);
+
+    but.textContent = '✓';
+}
diff --git a/src/librustdoc/html/static/noscript.css b/src/librustdoc/html/static/noscript.css
index c9fed989ec0..4d3332877c0 100644
--- a/src/librustdoc/html/static/noscript.css
+++ b/src/librustdoc/html/static/noscript.css
@@ -33,3 +33,8 @@ rules.
 	/* Since there is no toggle (the "[-]") when JS is disabled, no need for this margin either. */
 	margin-left: 0 !important;
 }
+
+#copy-path {
+	/* It requires JS to work so no need to display it in this case. */
+	display: none;
+}
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 6c90fd7c9ee..07dfb7f5cf0 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -424,7 +424,9 @@ nav.sub {
 	text-overflow: ellipsis;
 	margin: 0;
 }
-.docblock-short code {
+/* Wrap non-pre code blocks (`text`) but not (```text```). */
+.docblock > :not(pre) > code,
+.docblock-short > :not(pre) > code {
 	white-space: pre-wrap;
 }
 
@@ -1316,20 +1318,29 @@ h4 > .notable-traits {
 	outline: none;
 }
 
+#theme-picker, #settings-menu, .help-button, #copy-path {
+	padding: 4px;
+	width: 27px;
+	height: 29px;
+	border: 1px solid;
+	border-radius: 3px;
+	cursor: pointer;
+}
+
 .help-button {
 	right: 30px;
 	font-family: "Fira Sans", Arial, sans-serif;
 	text-align: center;
 	font-size: 17px;
+	padding-top: 2px;
 }
 
-#theme-picker, #settings-menu, .help-button {
-	padding: 4px;
-	width: 27px;
-	height: 29px;
-	border: 1px solid;
-	border-radius: 3px;
-	cursor: pointer;
+#copy-path {
+	height: 30px;
+	font-size: 18px;
+	margin-left: 10px;
+	padding: 0 6px;
+	width: 28px;
 }
 
 #theme-choices {
diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css
index 7374aee71f8..b24f4035ca8 100644
--- a/src/librustdoc/html/static/themes/ayu.css
+++ b/src/librustdoc/html/static/themes/ayu.css
@@ -498,7 +498,7 @@ kbd {
 	box-shadow-color: #c6cbd1;
 }
 
-#theme-picker, #settings-menu, .help-button {
+#theme-picker, #settings-menu, .help-button, #copy-path {
 	border-color: #5c6773;
 	background-color: #0f1419;
 	color: #fff;
@@ -510,7 +510,8 @@ kbd {
 
 #theme-picker:hover, #theme-picker:focus,
 #settings-menu:hover, #settings-menu:focus,
-.help-button:hover, .help-button:focus {
+.help-button:hover, .help-button:focus,
+#copy-path:hover, #copy-path:focus {
 	border-color: #e0e0e0;
 }
 
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index cf2d28bb43f..e863ed03f51 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -388,7 +388,7 @@ kbd {
 	box-shadow-color: #c6cbd1;
 }
 
-#theme-picker, #settings-menu, .help-button {
+#theme-picker, #settings-menu, .help-button, #copy-path {
 	border-color: #e0e0e0;
 	background: #f0f0f0;
 	color: #000;
@@ -396,7 +396,8 @@ kbd {
 
 #theme-picker:hover, #theme-picker:focus,
 #settings-menu:hover, #settings-menu:focus,
-.help-button:hover, .help-button:focus {
+.help-button:hover, .help-button:focus,
+#copy-path:hover, #copy-path:focus {
 	border-color: #ffb900;
 }
 
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index 7bf6793809c..9335dd96d29 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -380,14 +380,15 @@ kbd {
 	box-shadow-color: #c6cbd1;
 }
 
-#theme-picker, #settings-menu, .help-button {
+#theme-picker, #settings-menu, .help-button, #copy-path {
 	border-color: #e0e0e0;
 	background-color: #fff;
 }
 
 #theme-picker:hover, #theme-picker:focus,
 #settings-menu:hover, #settings-menu:focus,
-.help-button:hover, .help-button:focus {
+.help-button:hover, .help-button:focus,
+#copy-path:hover, #copy-path:focus {
 	border-color: #717171;
 }
 
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 073209c2468..c470dc57005 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -27,7 +27,7 @@ impl JsonRenderer<'_> {
         let clean::Item { span, name, attrs, kind, visibility, def_id } = item;
         let inner = match *kind {
             clean::StrippedItem(_) => return None,
-            x => from_clean_item_kind(x, self.tcx, &name),
+            kind => from_clean_item_kind(kind, self.tcx, &name),
         };
         Some(Item {
             id: from_def_id(def_id),
@@ -87,59 +87,78 @@ impl JsonRenderer<'_> {
     }
 }
 
+crate trait FromWithTcx<T> {
+    fn from_tcx(f: T, tcx: TyCtxt<'_>) -> Self;
+}
+
+crate trait IntoWithTcx<T> {
+    fn into_tcx(self, tcx: TyCtxt<'_>) -> T;
+}
+
+impl<T, U> IntoWithTcx<U> for T
+where
+    U: FromWithTcx<T>,
+{
+    fn into_tcx(self, tcx: TyCtxt<'_>) -> U {
+        U::from_tcx(self, tcx)
+    }
+}
+
 crate fn from_deprecation(deprecation: rustc_attr::Deprecation) -> Deprecation {
     #[rustfmt::skip]
     let rustc_attr::Deprecation { since, note, is_since_rustc_version: _, suggestion: _ } = deprecation;
     Deprecation { since: since.map(|s| s.to_string()), note: note.map(|s| s.to_string()) }
 }
 
-impl From<clean::GenericArgs> for GenericArgs {
-    fn from(args: clean::GenericArgs) -> Self {
+impl FromWithTcx<clean::GenericArgs> for GenericArgs {
+    fn from_tcx(args: clean::GenericArgs, tcx: TyCtxt<'_>) -> Self {
         use clean::GenericArgs::*;
         match args {
             AngleBracketed { args, bindings } => GenericArgs::AngleBracketed {
-                args: args.into_iter().map(Into::into).collect(),
-                bindings: bindings.into_iter().map(Into::into).collect(),
+                args: args.into_iter().map(|a| a.into_tcx(tcx)).collect(),
+                bindings: bindings.into_iter().map(|a| a.into_tcx(tcx)).collect(),
             },
             Parenthesized { inputs, output } => GenericArgs::Parenthesized {
-                inputs: inputs.into_iter().map(Into::into).collect(),
-                output: output.map(Into::into),
+                inputs: inputs.into_iter().map(|a| a.into_tcx(tcx)).collect(),
+                output: output.map(|a| a.into_tcx(tcx)),
             },
         }
     }
 }
 
-impl From<clean::GenericArg> for GenericArg {
-    fn from(arg: clean::GenericArg) -> Self {
+impl FromWithTcx<clean::GenericArg> for GenericArg {
+    fn from_tcx(arg: clean::GenericArg, tcx: TyCtxt<'_>) -> Self {
         use clean::GenericArg::*;
         match arg {
             Lifetime(l) => GenericArg::Lifetime(l.0.to_string()),
-            Type(t) => GenericArg::Type(t.into()),
-            Const(c) => GenericArg::Const(c.into()),
+            Type(t) => GenericArg::Type(t.into_tcx(tcx)),
+            Const(c) => GenericArg::Const(c.into_tcx(tcx)),
         }
     }
 }
 
-impl From<clean::Constant> for Constant {
-    fn from(constant: clean::Constant) -> Self {
-        let clean::Constant { type_, expr, value, is_literal } = constant;
-        Constant { type_: type_.into(), expr, value, is_literal }
+impl FromWithTcx<clean::Constant> for Constant {
+    fn from_tcx(constant: clean::Constant, tcx: TyCtxt<'_>) -> Self {
+        let expr = constant.expr(tcx);
+        let value = constant.value(tcx);
+        let is_literal = constant.is_literal(tcx);
+        Constant { type_: constant.type_.into_tcx(tcx), expr, value, is_literal }
     }
 }
 
-impl From<clean::TypeBinding> for TypeBinding {
-    fn from(binding: clean::TypeBinding) -> Self {
-        TypeBinding { name: binding.name.to_string(), binding: binding.kind.into() }
+impl FromWithTcx<clean::TypeBinding> for TypeBinding {
+    fn from_tcx(binding: clean::TypeBinding, tcx: TyCtxt<'_>) -> Self {
+        TypeBinding { name: binding.name.to_string(), binding: binding.kind.into_tcx(tcx) }
     }
 }
 
-impl From<clean::TypeBindingKind> for TypeBindingKind {
-    fn from(kind: clean::TypeBindingKind) -> Self {
+impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind {
+    fn from_tcx(kind: clean::TypeBindingKind, tcx: TyCtxt<'_>) -> Self {
         use clean::TypeBindingKind::*;
         match kind {
-            Equality { ty } => TypeBindingKind::Equality(ty.into()),
+            Equality { ty } => TypeBindingKind::Equality(ty.into_tcx(tcx)),
             Constraint { bounds } => {
-                TypeBindingKind::Constraint(bounds.into_iter().map(Into::into).collect())
+                TypeBindingKind::Constraint(bounds.into_iter().map(|a| a.into_tcx(tcx)).collect())
             }
         }
     }
@@ -152,34 +171,35 @@ crate fn from_def_id(did: DefId) -> Id {
 fn from_clean_item_kind(item: clean::ItemKind, tcx: TyCtxt<'_>, name: &Option<Symbol>) -> ItemEnum {
     use clean::ItemKind::*;
     match item {
-        ModuleItem(m) => ItemEnum::Module(m.into()),
-        ImportItem(i) => ItemEnum::Import(i.into()),
-        StructItem(s) => ItemEnum::Struct(s.into()),
-        UnionItem(u) => ItemEnum::Union(u.into()),
-        StructFieldItem(f) => ItemEnum::StructField(f.into()),
-        EnumItem(e) => ItemEnum::Enum(e.into()),
-        VariantItem(v) => ItemEnum::Variant(v.into()),
-        FunctionItem(f) => ItemEnum::Function(f.into()),
-        ForeignFunctionItem(f) => ItemEnum::Function(f.into()),
-        TraitItem(t) => ItemEnum::Trait(t.into()),
-        TraitAliasItem(t) => ItemEnum::TraitAlias(t.into()),
-        MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true)),
-        TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false)),
-        ImplItem(i) => ItemEnum::Impl(i.into()),
-        StaticItem(s) => ItemEnum::Static(from_clean_static(s, tcx)),
-        ForeignStaticItem(s) => ItemEnum::Static(from_clean_static(s, tcx)),
+        ModuleItem(m) => ItemEnum::Module(m.into_tcx(tcx)),
+        ImportItem(i) => ItemEnum::Import(i.into_tcx(tcx)),
+        StructItem(s) => ItemEnum::Struct(s.into_tcx(tcx)),
+        UnionItem(u) => ItemEnum::Union(u.into_tcx(tcx)),
+        StructFieldItem(f) => ItemEnum::StructField(f.into_tcx(tcx)),
+        EnumItem(e) => ItemEnum::Enum(e.into_tcx(tcx)),
+        VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)),
+        FunctionItem(f) => ItemEnum::Function(f.into_tcx(tcx)),
+        ForeignFunctionItem(f) => ItemEnum::Function(f.into_tcx(tcx)),
+        TraitItem(t) => ItemEnum::Trait(t.into_tcx(tcx)),
+        TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)),
+        MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, tcx)),
+        TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, tcx)),
+        ImplItem(i) => ItemEnum::Impl(i.into_tcx(tcx)),
+        StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
+        ForeignStaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
         ForeignTypeItem => ItemEnum::ForeignType,
-        TypedefItem(t, _) => ItemEnum::Typedef(t.into()),
-        OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into()),
-        ConstantItem(c) => ItemEnum::Constant(c.into()),
+        TypedefItem(t, _) => ItemEnum::Typedef(t.into_tcx(tcx)),
+        OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)),
+        ConstantItem(c) => ItemEnum::Constant(c.into_tcx(tcx)),
         MacroItem(m) => ItemEnum::Macro(m.source),
-        ProcMacroItem(m) => ItemEnum::ProcMacro(m.into()),
-        AssocConstItem(t, s) => ItemEnum::AssocConst { type_: t.into(), default: s },
+        ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_tcx(tcx)),
+        AssocConstItem(t, s) => ItemEnum::AssocConst { type_: t.into_tcx(tcx), default: s },
         AssocTypeItem(g, t) => ItemEnum::AssocType {
-            bounds: g.into_iter().map(Into::into).collect(),
-            default: t.map(Into::into),
+            bounds: g.into_iter().map(|x| x.into_tcx(tcx)).collect(),
+            default: t.map(|x| x.into_tcx(tcx)),
         },
-        StrippedItem(inner) => from_clean_item_kind(*inner, tcx, name),
+        // `convert_item` early returns `None` for striped items
+        StrippedItem(_) => unreachable!(),
         PrimitiveItem(_) | KeywordItem(_) => {
             panic!("{:?} is not supported for JSON output", item)
         }
@@ -190,18 +210,18 @@ fn from_clean_item_kind(item: clean::ItemKind, tcx: TyCtxt<'_>, name: &Option<Sy
     }
 }
 
-impl From<clean::Module> for Module {
-    fn from(module: clean::Module) -> Self {
+impl FromWithTcx<clean::Module> for Module {
+    fn from_tcx(module: clean::Module, _tcx: TyCtxt<'_>) -> Self {
         Module { is_crate: module.is_crate, items: ids(module.items) }
     }
 }
 
-impl From<clean::Struct> for Struct {
-    fn from(struct_: clean::Struct) -> Self {
+impl FromWithTcx<clean::Struct> for Struct {
+    fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self {
         let clean::Struct { struct_type, generics, fields, fields_stripped } = struct_;
         Struct {
             struct_type: from_ctor_kind(struct_type),
-            generics: generics.into(),
+            generics: generics.into_tcx(tcx),
             fields_stripped,
             fields: ids(fields),
             impls: Vec::new(), // Added in JsonRenderer::item
@@ -209,11 +229,11 @@ impl From<clean::Struct> for Struct {
     }
 }
 
-impl From<clean::Union> for Union {
-    fn from(struct_: clean::Union) -> Self {
+impl FromWithTcx<clean::Union> for Union {
+    fn from_tcx(struct_: clean::Union, tcx: TyCtxt<'_>) -> Self {
         let clean::Union { generics, fields, fields_stripped } = struct_;
         Union {
-            generics: generics.into(),
+            generics: generics.into_tcx(tcx),
             fields_stripped,
             fields: ids(fields),
             impls: Vec::new(), // Added in JsonRenderer::item
@@ -247,74 +267,81 @@ crate fn from_fn_header(header: &rustc_hir::FnHeader) -> HashSet<Qualifiers> {
     v
 }
 
-impl From<clean::Function> for Function {
-    fn from(function: clean::Function) -> Self {
+impl FromWithTcx<clean::Function> for Function {
+    fn from_tcx(function: clean::Function, tcx: TyCtxt<'_>) -> Self {
         let clean::Function { decl, generics, header } = function;
         Function {
-            decl: decl.into(),
-            generics: generics.into(),
+            decl: decl.into_tcx(tcx),
+            generics: generics.into_tcx(tcx),
             header: from_fn_header(&header),
             abi: header.abi.to_string(),
         }
     }
 }
 
-impl From<clean::Generics> for Generics {
-    fn from(generics: clean::Generics) -> Self {
+impl FromWithTcx<clean::Generics> for Generics {
+    fn from_tcx(generics: clean::Generics, tcx: TyCtxt<'_>) -> Self {
         Generics {
-            params: generics.params.into_iter().map(Into::into).collect(),
-            where_predicates: generics.where_predicates.into_iter().map(Into::into).collect(),
+            params: generics.params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
+            where_predicates: generics
+                .where_predicates
+                .into_iter()
+                .map(|x| x.into_tcx(tcx))
+                .collect(),
         }
     }
 }
 
-impl From<clean::GenericParamDef> for GenericParamDef {
-    fn from(generic_param: clean::GenericParamDef) -> Self {
-        GenericParamDef { name: generic_param.name.to_string(), kind: generic_param.kind.into() }
+impl FromWithTcx<clean::GenericParamDef> for GenericParamDef {
+    fn from_tcx(generic_param: clean::GenericParamDef, tcx: TyCtxt<'_>) -> Self {
+        GenericParamDef {
+            name: generic_param.name.to_string(),
+            kind: generic_param.kind.into_tcx(tcx),
+        }
     }
 }
 
-impl From<clean::GenericParamDefKind> for GenericParamDefKind {
-    fn from(kind: clean::GenericParamDefKind) -> Self {
+impl FromWithTcx<clean::GenericParamDefKind> for GenericParamDefKind {
+    fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self {
         use clean::GenericParamDefKind::*;
         match kind {
             Lifetime => GenericParamDefKind::Lifetime,
             Type { did: _, bounds, default, synthetic: _ } => GenericParamDefKind::Type {
-                bounds: bounds.into_iter().map(Into::into).collect(),
-                default: default.map(Into::into),
+                bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
+                default: default.map(|x| x.into_tcx(tcx)),
             },
-            Const { did: _, ty } => GenericParamDefKind::Const(ty.into()),
+            Const { did: _, ty } => GenericParamDefKind::Const(ty.into_tcx(tcx)),
         }
     }
 }
 
-impl From<clean::WherePredicate> for WherePredicate {
-    fn from(predicate: clean::WherePredicate) -> Self {
+impl FromWithTcx<clean::WherePredicate> for WherePredicate {
+    fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self {
         use clean::WherePredicate::*;
         match predicate {
             BoundPredicate { ty, bounds } => WherePredicate::BoundPredicate {
-                ty: ty.into(),
-                bounds: bounds.into_iter().map(Into::into).collect(),
+                ty: ty.into_tcx(tcx),
+                bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
             },
             RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate {
                 lifetime: lifetime.0.to_string(),
-                bounds: bounds.into_iter().map(Into::into).collect(),
+                bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
             },
             EqPredicate { lhs, rhs } => {
-                WherePredicate::EqPredicate { lhs: lhs.into(), rhs: rhs.into() }
+                WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) }
             }
         }
     }
 }
 
-impl From<clean::GenericBound> for GenericBound {
-    fn from(bound: clean::GenericBound) -> Self {
+impl FromWithTcx<clean::GenericBound> for GenericBound {
+    fn from_tcx(bound: clean::GenericBound, tcx: TyCtxt<'_>) -> Self {
         use clean::GenericBound::*;
         match bound {
             TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => {
                 GenericBound::TraitBound {
-                    trait_: trait_.into(),
-                    generic_params: generic_params.into_iter().map(Into::into).collect(),
+                    trait_: trait_.into_tcx(tcx),
+                    generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
                     modifier: from_trait_bound_modifier(modifier),
                 }
             }
@@ -332,47 +359,47 @@ crate fn from_trait_bound_modifier(modifier: rustc_hir::TraitBoundModifier) -> T
     }
 }
 
-impl From<clean::Type> for Type {
-    fn from(ty: clean::Type) -> Self {
+impl FromWithTcx<clean::Type> for Type {
+    fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
         use clean::Type::*;
         match ty {
             ResolvedPath { path, param_names, did, is_generic: _ } => Type::ResolvedPath {
                 name: path.whole_name(),
                 id: from_def_id(did),
-                args: path.segments.last().map(|args| Box::new(args.clone().args.into())),
+                args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
                 param_names: param_names
-                    .map(|v| v.into_iter().map(Into::into).collect())
+                    .map(|v| v.into_iter().map(|x| x.into_tcx(tcx)).collect())
                     .unwrap_or_default(),
             },
             Generic(s) => Type::Generic(s.to_string()),
             Primitive(p) => Type::Primitive(p.as_str().to_string()),
-            BareFunction(f) => Type::FunctionPointer(Box::new((*f).into())),
-            Tuple(t) => Type::Tuple(t.into_iter().map(Into::into).collect()),
-            Slice(t) => Type::Slice(Box::new((*t).into())),
-            Array(t, s) => Type::Array { type_: Box::new((*t).into()), len: s },
-            ImplTrait(g) => Type::ImplTrait(g.into_iter().map(Into::into).collect()),
+            BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
+            Tuple(t) => Type::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()),
+            Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))),
+            Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s },
+            ImplTrait(g) => Type::ImplTrait(g.into_iter().map(|x| x.into_tcx(tcx)).collect()),
             Never => Type::Never,
             Infer => Type::Infer,
             RawPointer(mutability, type_) => Type::RawPointer {
                 mutable: mutability == ast::Mutability::Mut,
-                type_: Box::new((*type_).into()),
+                type_: Box::new((*type_).into_tcx(tcx)),
             },
             BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef {
                 lifetime: lifetime.map(|l| l.0.to_string()),
                 mutable: mutability == ast::Mutability::Mut,
-                type_: Box::new((*type_).into()),
+                type_: Box::new((*type_).into_tcx(tcx)),
             },
             QPath { name, self_type, trait_ } => Type::QualifiedPath {
                 name: name.to_string(),
-                self_type: Box::new((*self_type).into()),
-                trait_: Box::new((*trait_).into()),
+                self_type: Box::new((*self_type).into_tcx(tcx)),
+                trait_: Box::new((*trait_).into_tcx(tcx)),
             },
         }
     }
 }
 
-impl From<clean::BareFunctionDecl> for FunctionPointer {
-    fn from(bare_decl: clean::BareFunctionDecl) -> Self {
+impl FromWithTcx<clean::BareFunctionDecl> for FunctionPointer {
+    fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self {
         let clean::BareFunctionDecl { unsafety, generic_params, decl, abi } = bare_decl;
         FunctionPointer {
             header: if let rustc_hir::Unsafety::Unsafe = unsafety {
@@ -382,24 +409,24 @@ impl From<clean::BareFunctionDecl> for FunctionPointer {
             } else {
                 HashSet::new()
             },
-            generic_params: generic_params.into_iter().map(Into::into).collect(),
-            decl: decl.into(),
+            generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
+            decl: decl.into_tcx(tcx),
             abi: abi.to_string(),
         }
     }
 }
 
-impl From<clean::FnDecl> for FnDecl {
-    fn from(decl: clean::FnDecl) -> Self {
+impl FromWithTcx<clean::FnDecl> for FnDecl {
+    fn from_tcx(decl: clean::FnDecl, tcx: TyCtxt<'_>) -> Self {
         let clean::FnDecl { inputs, output, c_variadic, attrs: _ } = decl;
         FnDecl {
             inputs: inputs
                 .values
                 .into_iter()
-                .map(|arg| (arg.name.to_string(), arg.type_.into()))
+                .map(|arg| (arg.name.to_string(), arg.type_.into_tcx(tcx)))
                 .collect(),
             output: match output {
-                clean::FnRetTy::Return(t) => Some(t.into()),
+                clean::FnRetTy::Return(t) => Some(t.into_tcx(tcx)),
                 clean::FnRetTy::DefaultReturn => None,
             },
             c_variadic,
@@ -407,22 +434,22 @@ impl From<clean::FnDecl> for FnDecl {
     }
 }
 
-impl From<clean::Trait> for Trait {
-    fn from(trait_: clean::Trait) -> Self {
+impl FromWithTcx<clean::Trait> for Trait {
+    fn from_tcx(trait_: clean::Trait, tcx: TyCtxt<'_>) -> Self {
         let clean::Trait { unsafety, items, generics, bounds, is_auto } = trait_;
         Trait {
             is_auto,
             is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
             items: ids(items),
-            generics: generics.into(),
-            bounds: bounds.into_iter().map(Into::into).collect(),
+            generics: generics.into_tcx(tcx),
+            bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
             implementors: Vec::new(), // Added in JsonRenderer::item
         }
     }
 }
 
-impl From<clean::Impl> for Impl {
-    fn from(impl_: clean::Impl) -> Self {
+impl FromWithTcx<clean::Impl> for Impl {
+    fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
         let clean::Impl {
             unsafety,
             generics,
@@ -436,37 +463,41 @@ impl From<clean::Impl> for Impl {
         } = impl_;
         Impl {
             is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
-            generics: generics.into(),
+            generics: generics.into_tcx(tcx),
             provided_trait_methods: provided_trait_methods
                 .into_iter()
                 .map(|x| x.to_string())
                 .collect(),
-            trait_: trait_.map(Into::into),
-            for_: for_.into(),
+            trait_: trait_.map(|x| x.into_tcx(tcx)),
+            for_: for_.into_tcx(tcx),
             items: ids(items),
             negative: negative_polarity,
             synthetic,
-            blanket_impl: blanket_impl.map(Into::into),
+            blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)),
         }
     }
 }
 
-crate fn from_function_method(function: clean::Function, has_body: bool) -> Method {
+crate fn from_function_method(
+    function: clean::Function,
+    has_body: bool,
+    tcx: TyCtxt<'_>,
+) -> Method {
     let clean::Function { header, decl, generics } = function;
     Method {
-        decl: decl.into(),
-        generics: generics.into(),
+        decl: decl.into_tcx(tcx),
+        generics: generics.into_tcx(tcx),
         header: from_fn_header(&header),
         abi: header.abi.to_string(),
         has_body,
     }
 }
 
-impl From<clean::Enum> for Enum {
-    fn from(enum_: clean::Enum) -> Self {
+impl FromWithTcx<clean::Enum> for Enum {
+    fn from_tcx(enum_: clean::Enum, tcx: TyCtxt<'_>) -> Self {
         let clean::Enum { variants, generics, variants_stripped } = enum_;
         Enum {
-            generics: generics.into(),
+            generics: generics.into_tcx(tcx),
             variants_stripped,
             variants: ids(variants),
             impls: Vec::new(), // Added in JsonRenderer::item
@@ -474,8 +505,8 @@ impl From<clean::Enum> for Enum {
     }
 }
 
-impl From<clean::VariantStruct> for Struct {
-    fn from(struct_: clean::VariantStruct) -> Self {
+impl FromWithTcx<clean::VariantStruct> for Struct {
+    fn from_tcx(struct_: clean::VariantStruct, _tcx: TyCtxt<'_>) -> Self {
         let clean::VariantStruct { struct_type, fields, fields_stripped } = struct_;
         Struct {
             struct_type: from_ctor_kind(struct_type),
@@ -487,19 +518,19 @@ impl From<clean::VariantStruct> for Struct {
     }
 }
 
-impl From<clean::Variant> for Variant {
-    fn from(variant: clean::Variant) -> Self {
+impl FromWithTcx<clean::Variant> for Variant {
+    fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
         use clean::Variant::*;
         match variant {
             CLike => Variant::Plain,
-            Tuple(t) => Variant::Tuple(t.into_iter().map(Into::into).collect()),
+            Tuple(t) => Variant::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()),
             Struct(s) => Variant::Struct(ids(s.fields)),
         }
     }
 }
 
-impl From<clean::Import> for Import {
-    fn from(import: clean::Import) -> Self {
+impl FromWithTcx<clean::Import> for Import {
+    fn from_tcx(import: clean::Import, _tcx: TyCtxt<'_>) -> Self {
         use clean::ImportKind::*;
         match import.kind {
             Simple(s) => Import {
@@ -518,8 +549,8 @@ impl From<clean::Import> for Import {
     }
 }
 
-impl From<clean::ProcMacro> for ProcMacro {
-    fn from(mac: clean::ProcMacro) -> Self {
+impl FromWithTcx<clean::ProcMacro> for ProcMacro {
+    fn from_tcx(mac: clean::ProcMacro, _tcx: TyCtxt<'_>) -> Self {
         ProcMacro {
             kind: from_macro_kind(mac.kind),
             helpers: mac.helpers.iter().map(|x| x.to_string()).collect(),
@@ -536,41 +567,43 @@ crate fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind {
     }
 }
 
-impl From<clean::Typedef> for Typedef {
-    fn from(typedef: clean::Typedef) -> Self {
+impl FromWithTcx<clean::Typedef> for Typedef {
+    fn from_tcx(typedef: clean::Typedef, tcx: TyCtxt<'_>) -> Self {
         let clean::Typedef { type_, generics, item_type: _ } = typedef;
-        Typedef { type_: type_.into(), generics: generics.into() }
+        Typedef { type_: type_.into_tcx(tcx), generics: generics.into_tcx(tcx) }
     }
 }
 
-impl From<clean::OpaqueTy> for OpaqueTy {
-    fn from(opaque: clean::OpaqueTy) -> Self {
+impl FromWithTcx<clean::OpaqueTy> for OpaqueTy {
+    fn from_tcx(opaque: clean::OpaqueTy, tcx: TyCtxt<'_>) -> Self {
         OpaqueTy {
-            bounds: opaque.bounds.into_iter().map(Into::into).collect(),
-            generics: opaque.generics.into(),
+            bounds: opaque.bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
+            generics: opaque.generics.into_tcx(tcx),
         }
     }
 }
 
-fn from_clean_static(stat: clean::Static, tcx: TyCtxt<'_>) -> Static {
-    Static {
-        type_: stat.type_.into(),
-        mutable: stat.mutability == ast::Mutability::Mut,
-        expr: stat.expr.map(|e| print_const_expr(tcx, e)).unwrap_or_default(),
+impl FromWithTcx<clean::Static> for Static {
+    fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self {
+        Static {
+            type_: stat.type_.into_tcx(tcx),
+            mutable: stat.mutability == ast::Mutability::Mut,
+            expr: stat.expr.map(|e| print_const_expr(tcx, e)).unwrap_or_default(),
+        }
     }
 }
 
-impl From<clean::TraitAlias> for TraitAlias {
-    fn from(alias: clean::TraitAlias) -> Self {
+impl FromWithTcx<clean::TraitAlias> for TraitAlias {
+    fn from_tcx(alias: clean::TraitAlias, tcx: TyCtxt<'_>) -> Self {
         TraitAlias {
-            generics: alias.generics.into(),
-            params: alias.bounds.into_iter().map(Into::into).collect(),
+            generics: alias.generics.into_tcx(tcx),
+            params: alias.bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
         }
     }
 }
 
-impl From<ItemType> for ItemKind {
-    fn from(kind: ItemType) -> Self {
+impl FromWithTcx<ItemType> for ItemKind {
+    fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self {
         use ItemType::*;
         match kind {
             Module => ItemKind::Module,
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index a4cdad69865..db3a0c5ceb1 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -24,7 +24,7 @@ use crate::error::Error;
 use crate::formats::cache::Cache;
 use crate::formats::FormatRenderer;
 use crate::html::render::cache::ExternalLocation;
-use crate::json::conversions::from_def_id;
+use crate::json::conversions::{from_def_id, IntoWithTcx};
 
 #[derive(Clone)]
 crate struct JsonRenderer<'tcx> {
@@ -108,7 +108,7 @@ impl JsonRenderer<'tcx> {
                                 .last()
                                 .map(Clone::clone),
                             visibility: types::Visibility::Public,
-                            inner: types::ItemEnum::Trait(trait_item.clone().into()),
+                            inner: types::ItemEnum::Trait(trait_item.clone().into_tcx(self.tcx)),
                             span: None,
                             docs: Default::default(),
                             links: Default::default(),
@@ -129,6 +129,8 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
         "json"
     }
 
+    const RUN_ON_MODULE: bool = false;
+
     fn init(
         krate: clean::Crate,
         options: RenderOptions,
@@ -169,8 +171,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
                 e.impls = self.get_impls(id)
             }
             let removed = self.index.borrow_mut().insert(from_def_id(id), new_item.clone());
+
             // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
-            // to make sure the items are unique.
+            // to make sure the items are unique. The main place this happens is when an item, is
+            // reexported in more than one place. See `rustdoc-json/reexport/in_root_and_mod`
             if let Some(old_item) = removed {
                 assert_eq!(old_item, new_item);
             }
@@ -225,7 +229,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
                 .map(|(k, (path, kind))| {
                     (
                         from_def_id(k),
-                        types::ItemSummary { crate_id: k.krate.as_u32(), path, kind: kind.into() },
+                        types::ItemSummary {
+                            crate_id: k.krate.as_u32(),
+                            path,
+                            kind: kind.into_tcx(self.tcx),
+                        },
                     )
                 })
                 .collect(),
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index a2f8eb3772e..ad269413ac6 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -216,8 +216,8 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
                 if let Some(ref tr) = impl_.trait_ {
                     debug!(
                         "impl {:#} for {:#} in {}",
-                        tr.print(&self.ctx.cache),
-                        impl_.for_.print(&self.ctx.cache),
+                        tr.print(&self.ctx.cache, self.ctx.tcx),
+                        impl_.for_.print(&self.ctx.cache, self.ctx.tcx),
                         filename,
                     );
 
@@ -228,7 +228,11 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
                     // inherent impls *can* be documented, and those docs show up, but in most
                     // cases it doesn't make sense, as all methods on a type are in one single
                     // impl block
-                    debug!("impl {:#} in {}", impl_.for_.print(&self.ctx.cache), filename);
+                    debug!(
+                        "impl {:#} in {}",
+                        impl_.for_.print(&self.ctx.cache, self.ctx.tcx),
+                        filename
+                    );
                 }
             }
             _ => {
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 499931f7e96..55978ca551b 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -950,6 +950,7 @@ impl LinkCollector<'_, '_> {
         }
 
         let link = ori_link.link.replace("`", "");
+        let no_backticks_range = range_between_backticks(&ori_link);
         let parts = link.split('#').collect::<Vec<_>>();
         let (link, extra_fragment) = if parts.len() > 2 {
             // A valid link can't have multiple #'s
@@ -973,10 +974,15 @@ impl LinkCollector<'_, '_> {
         };
 
         // Parse and strip the disambiguator from the link, if present.
-        let (mut path_str, disambiguator) = if let Ok((d, path)) = Disambiguator::from_str(&link) {
-            (path.trim(), Some(d))
-        } else {
-            (link.trim(), None)
+        let (mut path_str, disambiguator) = match Disambiguator::from_str(&link) {
+            Ok(Some((d, path))) => (path.trim(), Some(d)),
+            Ok(None) => (link.trim(), None),
+            Err((err_msg, relative_range)) => {
+                let disambiguator_range = (no_backticks_range.start + relative_range.start)
+                    ..(no_backticks_range.start + relative_range.end);
+                disambiguator_error(self.cx, &item, dox, disambiguator_range, &err_msg);
+                return None;
+            }
         };
 
         if path_str.contains(|ch: char| !(ch.is_alphanumeric() || ":_<>, !*&;".contains(ch))) {
@@ -1488,6 +1494,27 @@ impl LinkCollector<'_, '_> {
     }
 }
 
+/// Get the section of a link between the backticks,
+/// or the whole link if there aren't any backticks.
+///
+/// For example:
+///
+/// ```text
+/// [`Foo`]
+///   ^^^
+/// ```
+fn range_between_backticks(ori_link: &MarkdownLink) -> Range<usize> {
+    let after_first_backtick_group = ori_link.link.bytes().position(|b| b != b'`').unwrap_or(0);
+    let before_second_backtick_group = ori_link
+        .link
+        .bytes()
+        .skip(after_first_backtick_group)
+        .position(|b| b == b'`')
+        .unwrap_or(ori_link.link.len());
+    (ori_link.range.start + after_first_backtick_group)
+        ..(ori_link.range.start + before_second_backtick_group)
+}
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 /// Disambiguators for a link.
 enum Disambiguator {
@@ -1514,27 +1541,14 @@ impl Disambiguator {
         }
     }
 
-    /// Given a link, parse and return `(disambiguator, path_str)`
-    fn from_str(link: &str) -> Result<(Self, &str), ()> {
+    /// Given a link, parse and return `(disambiguator, path_str)`.
+    ///
+    /// This returns `Ok(Some(...))` if a disambiguator was found,
+    /// `Ok(None)` if no disambiguator was found, or `Err(...)`
+    /// if there was a problem with the disambiguator.
+    fn from_str(link: &str) -> Result<Option<(Self, &str)>, (String, Range<usize>)> {
         use Disambiguator::{Kind, Namespace as NS, Primitive};
 
-        let find_suffix = || {
-            let suffixes = [
-                ("!()", DefKind::Macro(MacroKind::Bang)),
-                ("()", DefKind::Fn),
-                ("!", DefKind::Macro(MacroKind::Bang)),
-            ];
-            for &(suffix, kind) in &suffixes {
-                if let Some(link) = link.strip_suffix(suffix) {
-                    // Avoid turning `!` or `()` into an empty string
-                    if !link.is_empty() {
-                        return Ok((Kind(kind), link));
-                    }
-                }
-            }
-            Err(())
-        };
-
         if let Some(idx) = link.find('@') {
             let (prefix, rest) = link.split_at(idx);
             let d = match prefix {
@@ -1551,11 +1565,24 @@ impl Disambiguator {
                 "value" => NS(Namespace::ValueNS),
                 "macro" => NS(Namespace::MacroNS),
                 "prim" | "primitive" => Primitive,
-                _ => return find_suffix(),
+                _ => return Err((format!("unknown disambiguator `{}`", prefix), 0..idx)),
             };
-            Ok((d, &rest[1..]))
+            Ok(Some((d, &rest[1..])))
         } else {
-            find_suffix()
+            let suffixes = [
+                ("!()", DefKind::Macro(MacroKind::Bang)),
+                ("()", DefKind::Fn),
+                ("!", DefKind::Macro(MacroKind::Bang)),
+            ];
+            for &(suffix, kind) in &suffixes {
+                if let Some(link) = link.strip_suffix(suffix) {
+                    // Avoid turning `!` or `()` into an empty string
+                    if !link.is_empty() {
+                        return Ok(Some((Kind(kind), link)));
+                    }
+                }
+            }
+            Ok(None)
         }
     }
 
@@ -1979,6 +2006,17 @@ fn anchor_failure(
     });
 }
 
+/// Report an error in the link disambiguator.
+fn disambiguator_error(
+    cx: &DocContext<'_>,
+    item: &Item,
+    dox: &str,
+    link_range: Range<usize>,
+    msg: &str,
+) {
+    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, item, dox, &link_range, |_diag, _sp| {});
+}
+
 /// Report an ambiguity error, where there were multiple possible resolutions.
 fn ambiguity_error(
     cx: &DocContext<'_>,
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 17a66d1788e..ca30d8f0d46 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -72,10 +72,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
 
     crate fn visit(mut self, krate: &'tcx hir::Crate<'_>) -> Module<'tcx> {
         let mut top_level_module = self.visit_mod_contents(
-            krate.item.span,
+            krate.item.inner,
             &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public },
             hir::CRATE_HIR_ID,
-            &krate.item.module,
+            &krate.item,
             self.cx.tcx.crate_name,
         );
         top_level_module.is_crate = true;
diff --git a/src/llvm-project b/src/llvm-project
-Subproject c3a26cbf6e73f2c5f8d03cee1f151d90a266ef3
+Subproject 0abbcc04d8375661a0637896b9ae5dc37a99dc7
diff --git a/src/test/assembly/asm/aarch64-modifiers.rs b/src/test/assembly/asm/aarch64-modifiers.rs
index 150997ee807..d4a44b17392 100644
--- a/src/test/assembly/asm/aarch64-modifiers.rs
+++ b/src/test/assembly/asm/aarch64-modifiers.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // assembly-output: emit-asm
 // compile-flags: -O
 // compile-flags: --target aarch64-unknown-linux-gnu
diff --git a/src/test/assembly/asm/aarch64-types.rs b/src/test/assembly/asm/aarch64-types.rs
index 8dd1f3c873f..aa25562d323 100644
--- a/src/test/assembly/asm/aarch64-types.rs
+++ b/src/test/assembly/asm/aarch64-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // assembly-output: emit-asm
 // compile-flags: --target aarch64-unknown-linux-gnu
 // needs-llvm-components: aarch64
diff --git a/src/test/assembly/asm/arm-modifiers.rs b/src/test/assembly/asm/arm-modifiers.rs
index ad4ab63f265..bb6cc1c9873 100644
--- a/src/test/assembly/asm/arm-modifiers.rs
+++ b/src/test/assembly/asm/arm-modifiers.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // assembly-output: emit-asm
 // compile-flags: -O
 // compile-flags: --target armv7-unknown-linux-gnueabihf
diff --git a/src/test/assembly/asm/arm-types.rs b/src/test/assembly/asm/arm-types.rs
index 09901a7a39c..b16fde571af 100644
--- a/src/test/assembly/asm/arm-types.rs
+++ b/src/test/assembly/asm/arm-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // assembly-output: emit-asm
 // compile-flags: --target armv7-unknown-linux-gnueabihf
 // compile-flags: -C target-feature=+neon
diff --git a/src/test/assembly/asm/hexagon-types.rs b/src/test/assembly/asm/hexagon-types.rs
index 95135a3e5dd..40352cdb4cd 100644
--- a/src/test/assembly/asm/hexagon-types.rs
+++ b/src/test/assembly/asm/hexagon-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // assembly-output: emit-asm
 // compile-flags: --target hexagon-unknown-linux-musl
 // needs-llvm-components: hexagon
diff --git a/src/test/assembly/asm/mips-types.rs b/src/test/assembly/asm/mips-types.rs
index 04e840dc166..60cfebdd992 100644
--- a/src/test/assembly/asm/mips-types.rs
+++ b/src/test/assembly/asm/mips-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // revisions: mips32 mips64
 // assembly-output: emit-asm
 //[mips32] compile-flags: --target mips-unknown-linux-gnu
diff --git a/src/test/assembly/asm/nvptx-types.rs b/src/test/assembly/asm/nvptx-types.rs
index 77fd5141357..75b6371fb70 100644
--- a/src/test/assembly/asm/nvptx-types.rs
+++ b/src/test/assembly/asm/nvptx-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // assembly-output: emit-asm
 // compile-flags: --target nvptx64-nvidia-cuda
 // compile-flags: --crate-type cdylib
diff --git a/src/test/assembly/asm/riscv-types.rs b/src/test/assembly/asm/riscv-types.rs
index 47518cdcf16..1ba73fcac9d 100644
--- a/src/test/assembly/asm/riscv-types.rs
+++ b/src/test/assembly/asm/riscv-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // revisions: riscv64 riscv32
 // assembly-output: emit-asm
 //[riscv64] compile-flags: --target riscv64imac-unknown-none-elf
diff --git a/src/test/assembly/asm/wasm-types.rs b/src/test/assembly/asm/wasm-types.rs
index 94ca526222a..a071a850c22 100644
--- a/src/test/assembly/asm/wasm-types.rs
+++ b/src/test/assembly/asm/wasm-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // assembly-output: emit-asm
 // compile-flags: --target wasm32-unknown-unknown
 // compile-flags: --crate-type cdylib
diff --git a/src/test/assembly/asm/x86-modifiers.rs b/src/test/assembly/asm/x86-modifiers.rs
index e538167cd46..da2dc51d69e 100644
--- a/src/test/assembly/asm/x86-modifiers.rs
+++ b/src/test/assembly/asm/x86-modifiers.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // revisions: x86_64 i686
 // assembly-output: emit-asm
 // compile-flags: -O
diff --git a/src/test/assembly/asm/x86-types.rs b/src/test/assembly/asm/x86-types.rs
index f636f1f5296..e0190d3bdae 100644
--- a/src/test/assembly/asm/x86-types.rs
+++ b/src/test/assembly/asm/x86-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // revisions: x86_64 i686
 // assembly-output: emit-asm
 //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
diff --git a/src/test/codegen/alloc-optimisation.rs b/src/test/codegen/alloc-optimisation.rs
index c3ffaeb9547..5b27f3f4545 100644
--- a/src/test/codegen/alloc-optimisation.rs
+++ b/src/test/codegen/alloc-optimisation.rs
@@ -1,5 +1,5 @@
 //
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // compile-flags: -O
 #![crate_type="lib"]
 
diff --git a/src/test/codegen/binary-search-index-no-bound-check.rs b/src/test/codegen/binary-search-index-no-bound-check.rs
new file mode 100644
index 00000000000..110d1d55626
--- /dev/null
+++ b/src/test/codegen/binary-search-index-no-bound-check.rs
@@ -0,0 +1,19 @@
+// min-llvm-version: 11.0.0
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+#![crate_type = "lib"]
+
+// Make sure no bounds checks are emitted when slicing or indexing
+// with an index from `binary_search`.
+
+// CHECK-LABEL: @binary_search_index_no_bounds_check
+#[no_mangle]
+pub fn binary_search_index_no_bounds_check(s: &[u8]) -> u8 {
+    // CHECK-NOT: panic
+    // CHECK-NOT: slice_index_len_fail
+    if let Ok(idx) = s.binary_search(&b'\\') {
+        s[idx]
+    } else {
+        42
+    }
+}
diff --git a/src/test/codegen/issue-83623-SIMD-PartialEq.rs b/src/test/codegen/issue-83623-SIMD-PartialEq.rs
new file mode 100644
index 00000000000..b22b7f52402
--- /dev/null
+++ b/src/test/codegen/issue-83623-SIMD-PartialEq.rs
@@ -0,0 +1,46 @@
+// This test checks that jumps generated by logical operators can be optimized away
+
+// compile-flags: -Copt-level=3
+// only-64bit
+
+#![crate_type="lib"]
+
+pub struct Blueprint {
+    pub fuel_tank_size: u32,
+    pub payload: u32,
+    pub wheel_diameter: u32,
+    pub wheel_width: u32,
+    pub storage: u32,
+}
+
+// && chains should not prevent SIMD optimizations for primitives
+impl PartialEq for Blueprint{
+    fn eq(&self, other: &Self)->bool{
+       // CHECK-NOT: call{{.*}}bcmp
+       // CHECK-NOT: call{{.*}}memcmp
+       // CHECK-NOT: br {{.*}}
+       self.fuel_tank_size == other.fuel_tank_size
+            && self.payload == other.payload
+            && self.wheel_diameter == other.wheel_diameter
+            && self.wheel_width == other.wheel_width
+            && self.storage == other.storage
+    }
+}
+
+#[derive(PartialEq)]
+pub struct Blueprint2 {
+    pub fuel_tank_size: u32,
+    pub payload: u32,
+    pub wheel_diameter: u32,
+    pub wheel_width: u32,
+    pub storage: u32,
+}
+
+// Derived PartialEq should not generate jumps and should use SIMD
+#[no_mangle]
+pub fn partial_eq_should_not_jump(a: &Blueprint2, b:&Blueprint2)->bool{
+    // CHECK-NOT: call{{.*}}bcmp
+    // CHECK-NOT: call{{.*}}memcmp
+    // CHECK-NOT: br {{.*}}
+    a==b
+}
diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
index 56466a78d5a..ae13d91ddeb 100644
--- a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
+++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
@@ -1,6 +1,5 @@
 // ignore-tidy-linelength
 // compile-flags: -C no-prepopulate-passes
-// min-llvm-version 8.0
 
 #![crate_type = "lib"]
 
diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs
index ed67b2dcb04..c8530c70f78 100644
--- a/src/test/incremental/hashes/function_interfaces.rs
+++ b/src/test/incremental/hashes/function_interfaces.rs
@@ -118,7 +118,7 @@ pub fn type_parameter<T>() {}
 pub fn lifetime_parameter() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn lifetime_parameter<'a>() {}
 
@@ -150,7 +150,7 @@ pub fn lifetime_bound<'a, T>() {}
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg = "cfail2",
-    except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of"
+    except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
 pub fn lifetime_bound<'a, T: 'a>() {}
@@ -183,7 +183,7 @@ pub fn second_lifetime_bound<'a, 'b, T: 'a>() {}
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg = "cfail2",
-    except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of"
+    except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
 pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {}
diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs
index ae8f2ace217..ee7b258cec4 100644
--- a/src/test/incremental/hashes/inherent_impls.rs
+++ b/src/test/incremental/hashes/inherent_impls.rs
@@ -312,7 +312,7 @@ impl Foo {
     // if we lower generics before the body, then the `HirId` for
     // things in the body will be affected. So if you start to see
     // `typeck` appear dirty, that might be the cause. -nmatsakis
-    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig")]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_lifetime_parameter_to_method<'a>(&self) { }
 }
@@ -360,7 +360,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of"
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { }
@@ -388,7 +388,7 @@ impl Foo {
     // body will be affected. So if you start to see `typeck`
     // appear dirty, that might be the cause. -nmatsakis
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,\
-                                        type_of")]
+                                        type_of,fn_sig")]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { }
 }
diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
index 4e990dd6b70..2566d745ecd 100644
--- a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
+++ b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
@@ -22,7 +22,7 @@
 -                                          // + ty: &i32
 -                                          // + val: Value(Scalar(alloc0))
 +                                          // + ty: &[&i32; 1]
-+                                          // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
++                                          // + val: Unevaluated(BAR, [], Some(promoted[0]))
                                            // mir::Constant
 -                                          // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34
 -                                          // + literal: Const { ty: &i32, val: Value(Scalar(alloc0)) }
diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
index 0a9a3f3c2c5..093e228a0ce 100644
--- a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
+++ b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
@@ -24,7 +24,7 @@
 -                                          // + ty: *const i32
 -                                          // + val: Value(Scalar(alloc2))
 +                                          // + ty: &[&i32; 1]
-+                                          // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
++                                          // + val: Unevaluated(FOO, [], Some(promoted[0]))
                                            // mir::Constant
 -                                          // + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43
 -                                          // + literal: Const { ty: *const i32, val: Value(Scalar(alloc2)) }
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
index 0535b45aa9f..0517e7fac40 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
@@ -28,7 +28,7 @@
           _9 = const main::promoted[0];    // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
                                            // ty::Const
                                            // + ty: &[i32; 3]
-                                           // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
+                                           // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
                                            // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
index 0535b45aa9f..0517e7fac40 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
@@ -28,7 +28,7 @@
           _9 = const main::promoted[0];    // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
                                            // ty::Const
                                            // + ty: &[i32; 3]
-                                           // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
+                                           // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
                                            // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
index 81e6937b1b3..28c80b346e7 100644
--- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
@@ -19,7 +19,7 @@
           _3 = const FOO;                  // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
                                            // ty::Const
                                            // + ty: &i32
-                                           // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main::FOO), const_param_did: None }, substs: [], promoted: None })
+                                           // + val: Unevaluated(FOO, [], None)
                                            // mir::Constant
                                            // + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
                                            // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main::FOO), const_param_did: None }, substs: [], promoted: None }) }
diff --git a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff
index 9126b9953ed..ae77443e019 100644
--- a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff
@@ -14,7 +14,7 @@
           _4 = const main::promoted[0];    // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
                                            // ty::Const
                                            // + ty: &i32
-                                           // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
+                                           // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/ref_deref.rs:5:6: 5:10
                                            // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
index e1c8085b31b..402a28f3f9f 100644
--- a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
+++ b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
@@ -17,7 +17,7 @@
 +         _4 = const main::promoted[0];    // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
 +                                          // ty::Const
 +                                          // + ty: &i32
-+                                          // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
++                                          // + val: Unevaluated(main, [], Some(promoted[0]))
 +                                          // mir::Constant
 +                                          // + span: $DIR/ref_deref.rs:5:6: 5:10
 +                                          // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
index ce1720698c7..b97d7d1be15 100644
--- a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
@@ -14,7 +14,7 @@
           _4 = const main::promoted[0];    // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
                                            // ty::Const
                                            // + ty: &(i32, i32)
-                                           // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
+                                           // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/ref_deref_project.rs:5:6: 5:17
                                            // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
index 93ba9de8202..48ede27112c 100644
--- a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
+++ b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
@@ -17,7 +17,7 @@
 +         _4 = const main::promoted[0];    // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
 +                                          // ty::Const
 +                                          // + ty: &(i32, i32)
-+                                          // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
++                                          // + val: Unevaluated(main, [], Some(promoted[0]))
 +                                          // mir::Constant
 +                                          // + span: $DIR/ref_deref_project.rs:5:6: 5:17
 +                                          // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
index 610e3c25573..27791852d6d 100644
--- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
@@ -21,7 +21,7 @@
           _9 = const main::promoted[0];    // scope 0 at $DIR/slice_len.rs:5:6: 5:19
                                            // ty::Const
                                            // + ty: &[u32; 3]
-                                           // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
+                                           // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/slice_len.rs:5:6: 5:19
                                            // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
index 610e3c25573..27791852d6d 100644
--- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
@@ -21,7 +21,7 @@
           _9 = const main::promoted[0];    // scope 0 at $DIR/slice_len.rs:5:6: 5:19
                                            // ty::Const
                                            // + ty: &[u32; 3]
-                                           // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
+                                           // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/slice_len.rs:5:6: 5:19
                                            // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
index caa02abf019..3a50ed224b5 100644
--- a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
+++ b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
@@ -51,7 +51,7 @@
       }
   
       bb2: {
-          discriminant(_6) = 2;            // scope 1 at $DIR/funky_arms.rs:21:17: 21:41
+          discriminant(_6) = 1;            // scope 1 at $DIR/funky_arms.rs:21:17: 21:41
           goto -> bb4;                     // scope 1 at $DIR/funky_arms.rs:19:16: 22:6
       }
   
diff --git a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
index 0b5dc2b20fc..1aabee83be6 100644
--- a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
@@ -35,7 +35,7 @@ fn bar() -> bool {
         _10 = const bar::promoted[1];    // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
                                          // ty::Const
                                          // + ty: &i32
-                                         // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) })
+                                         // + val: Unevaluated(bar, [], Some(promoted[1]))
                                          // mir::Constant
                                          // + span: $DIR/inline-retag.rs:12:7: 12:9
                                          // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) }
@@ -49,7 +49,7 @@ fn bar() -> bool {
         _9 = const bar::promoted[0];     // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
                                          // ty::Const
                                          // + ty: &i32
-                                         // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
+                                         // + val: Unevaluated(bar, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/inline-retag.rs:12:11: 12:14
                                          // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
index 1ba56016776..95a8ef997fa 100644
--- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
@@ -63,7 +63,7 @@
           _20 = const main::promoted[0];   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &i32
-                                           // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
+                                           // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
index 1ba56016776..95a8ef997fa 100644
--- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
@@ -63,7 +63,7 @@
           _20 = const main::promoted[0];   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &i32
-                                           // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
+                                           // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
index 245f0e9d000..261eb3b27ea 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
@@ -84,7 +84,7 @@
           _28 = const main::promoted[0];   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &i32
-                                           // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
+                                           // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
index 245f0e9d000..261eb3b27ea 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
@@ -84,7 +84,7 @@
           _28 = const main::promoted[0];   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &i32
-                                           // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
+                                           // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
index 83650d837b0..a37df4da9ae 100644
--- a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
+++ b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
@@ -47,7 +47,7 @@
           _19 = const discriminant::<T>::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
                                            // ty::Const
                                            // + ty: &i32
-                                           // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) })
+                                           // + val: Unevaluated(discriminant, [T], Some(promoted[2]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:70:42: 70:44
                                            // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) }
@@ -71,7 +71,7 @@
           _18 = const discriminant::<T>::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
                                            // ty::Const
                                            // + ty: &()
-                                           // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) })
+                                           // + val: Unevaluated(discriminant, [T], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:71:42: 71:45
                                            // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) }
@@ -95,7 +95,7 @@
           _17 = const discriminant::<T>::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
                                            // ty::Const
                                            // + ty: &E
-                                           // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) })
+                                           // + val: Unevaluated(discriminant, [T], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:72:42: 72:47
                                            // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
index 242138754c5..1921b935941 100644
--- a/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
+++ b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
@@ -54,7 +54,7 @@ fn full_tested_match() -> () {
         _11 = const full_tested_match::promoted[0]; // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15
                                          // ty::Const
                                          // + ty: &std::option::Option<i32>
-                                         // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
+                                         // + val: Unevaluated(full_tested_match, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/match_false_edges.rs:16:14: 16:15
                                          // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
index d25f98db9f6..894f64c7767 100644
--- a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
@@ -149,7 +149,7 @@ fn main() -> () {
         _27 = const main::promoted[0];   // scope 7 at $DIR/retag.rs:47:21: 47:23
                                          // ty::Const
                                          // + ty: &i32
-                                         // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) })
+                                         // + val: Unevaluated(main, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/retag.rs:47:21: 47:23
                                          // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
diff --git a/src/test/run-make-fulldeps/coverage-llvmir/Makefile b/src/test/run-make-fulldeps/coverage-llvmir/Makefile
index 86af7e41ae1..7d9121ee2f8 100644
--- a/src/test/run-make-fulldeps/coverage-llvmir/Makefile
+++ b/src/test/run-make-fulldeps/coverage-llvmir/Makefile
@@ -17,7 +17,7 @@ else
 	COMDAT_IF_SUPPORTED=, comdat
 endif
 
-DEFINE_INTERNAL=define hidden
+DEFINE_INTERNAL=define internal
 
 ifdef IS_WINDOWS
 	LLVM_FILECHECK_OPTIONS=\
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generics.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generics.txt
index 6f28c089093..7b38ffb87cb 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generics.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generics.txt
@@ -29,12 +29,12 @@
    18|      2|        println!("BOOM times {}!!!", self.strength);
    19|      2|    }
   ------------------
-  | <generics::Firework<f64> as core::ops::drop::Drop>::drop:
+  | <generics::Firework<i32> as core::ops::drop::Drop>::drop:
   |   17|      1|    fn drop(&mut self) {
   |   18|      1|        println!("BOOM times {}!!!", self.strength);
   |   19|      1|    }
   ------------------
-  | <generics::Firework<i32> as core::ops::drop::Drop>::drop:
+  | <generics::Firework<f64> as core::ops::drop::Drop>::drop:
   |   17|      1|    fn drop(&mut self) {
   |   18|      1|        println!("BOOM times {}!!!", self.strength);
   |   19|      1|    }
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt
index 380869d62a8..cdcbd8fca94 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt
@@ -36,12 +36,12 @@
    22|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
    23|      2|}
   ------------------
-  | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+  | used_crate::used_only_from_this_lib_crate_generic_function::<&str>:
   |   21|      1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
   |   22|      1|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
   |   23|      1|}
   ------------------
-  | used_crate::used_only_from_this_lib_crate_generic_function::<&str>:
+  | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
   |   21|      1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
   |   22|      1|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
   |   23|      1|}
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_inline_crate.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_inline_crate.txt
index 0853dc9c014..cc98956e307 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_inline_crate.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_inline_crate.txt
@@ -30,29 +30,12 @@
                    ^0
    29|      1|    use_this_lib_crate();
    30|      1|}
-  ------------------
-  | used_inline_crate::used_inline_function:
-  |   20|      1|pub fn used_inline_function() {
-  |   21|       |    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-  |   22|       |    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-  |   23|       |    // dependent conditions.
-  |   24|      1|    let is_true = std::env::args().len() == 1;
-  |   25|      1|    let mut countdown = 0;
-  |   26|      1|    if is_true {
-  |   27|      1|        countdown = 10;
-  |   28|      1|    }
-  |                   ^0
-  |   29|      1|    use_this_lib_crate();
-  |   30|      1|}
-  ------------------
-  | Unexecuted instantiation: used_inline_crate::used_inline_function
-  ------------------
-   31|       |// Expect for above function:
-   32|       |//
-   33|       |// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
-   34|       |//
-   35|       |// With `#[inline(always)]` this function is instantiated twice, in both the library crate (which
-   36|       |// does not use it) and the `uses_inline_crate` binary (which does use/call it).
+   31|       |
+   32|       |
+   33|       |
+   34|       |
+   35|       |
+   36|       |
    37|       |
    38|       |#[inline(always)]
    39|      2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.conditions/conditions.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.conditions/conditions.main.-------.InstrumentCoverage.0.html
index 0aa6fe65686..3d1b737ec2d 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.conditions/conditions.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.conditions/conditions.main.-------.InstrumentCoverage.0.html
@@ -83,7 +83,7 @@ For revisions in Pull Requests (PR):
 5:13-7:6: @1[1]: _2 = const ()">    }<span class="annotation">⦉@1</span></span></span><span><span class="code even" style="--layer: 1" title="7:6-7:6: @2[0]: _2 = const ()"><span class="annotation">@2⦊</span>‸<span class="annotation">⦉@2</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    const B: u32 = 100;</span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code odd" style="--layer: 1" title="10:9-10:10: @21[1]: FakeRead(ForLet, _4)"><span class="annotation">@21⦊</span>x<span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0"> = if </span><span><span class="code even" style="--layer: 1" title="10:16-10:25: @3[5]: _6 = _1
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code odd" style="--layer: 1" title="10:9-10:10: @19[1]: FakeRead(ForLet, _4)"><span class="annotation">@19⦊</span>x<span class="annotation">⦉@19</span></span></span><span class="code" style="--layer: 0"> = if </span><span><span class="code even" style="--layer: 1" title="10:16-10:25: @3[5]: _6 = _1
 10:16-10:29: @3[6]: _5 = Gt(move _6, const 7_u32)"><span class="annotation">@3⦊</span>countdown &gt; 7<span class="annotation">⦉@3</span></span></span><span class="code" style="--layer: 0"> {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="11:9-11:23: @4[0]: _7 = CheckedSub(_1, const 4_u32)
 11:9-11:23: @6[0]: _1 = move (_7.0: u32)
@@ -94,214 +94,214 @@ For revisions in Pull Requests (PR):
 <span class="line"><span class="code" style="--layer: 0">    } else if </span><span><span class="code even" style="--layer: 1" title="13:15-13:24: @5[2]: _9 = _1
 13:15-13:28: @5[3]: _8 = Gt(move _9, const 2_u32)"><span class="annotation">@5⦊</span>countdown &gt; 2<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"> {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code odd" style="--layer: 1" title="14:12-14:21: @7[5]: _14 = _1
-14:12-14:25: @7[6]: _13 = Lt(move _14, const 1_u32)"><span class="annotation">@7⦊</span>countdown &lt; 1<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="14:29-14:38: @15[2]: _16 = _1
-14:29-14:42: @15[3]: _15 = Gt(move _16, const 5_u32)"><span class="annotation">@15⦊</span>countdown &gt; 5<span class="annotation">⦉@15</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="14:46-14:55: @11[2]: _18 = _1
-14:46-14:60: @11[3]: _17 = Ne(move _18, const 9_u32)"><span class="annotation">@11⦊</span>countdown != 9<span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="15:13-15:26: @17[0]: _1 = const 0_u32
-14:61-16:10: @17[1]: _10 = const ()"><span class="annotation">@17⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="15:13-15:26: @17[0]: _1 = const 0_u32
-14:61-16:10: @17[1]: _10 = const ()">            countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="15:13-15:26: @17[0]: _1 = const 0_u32
-14:61-16:10: @17[1]: _10 = const ()">        }<span class="annotation">⦉@17</span></span></span><span><span class="code odd" style="--layer: 1" title="16:10-16:10: @18[0]: _10 = const ()"><span class="annotation">@18⦊</span>‸<span class="annotation">⦉@18</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="17:9-17:23: @19[2]: _19 = CheckedSub(_1, const 5_u32)
-17:9-17:23: @20[0]: _1 = move (_19.0: u32)
-18:9-18:18: @20[1]: _4 = _1"><span class="annotation">@19,20⦊</span>countdown -= 5;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="17:9-17:23: @19[2]: _19 = CheckedSub(_1, const 5_u32)
-17:9-17:23: @20[0]: _1 = move (_19.0: u32)
-18:9-18:18: @20[1]: _4 = _1">        countdown<span class="annotation">⦉@19,20</span></span></span><span class="code" style="--layer: 0"></span></span>
+14:12-14:25: @7[6]: _13 = Lt(move _14, const 1_u32)"><span class="annotation">@7⦊</span>countdown &lt; 1<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="14:29-14:38: @13[2]: _16 = _1
+14:29-14:42: @13[3]: _15 = Gt(move _16, const 5_u32)"><span class="annotation">@13⦊</span>countdown &gt; 5<span class="annotation">⦉@13</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="14:46-14:55: @10[2]: _18 = _1
+14:46-14:60: @10[3]: _17 = Ne(move _18, const 9_u32)"><span class="annotation">@10⦊</span>countdown != 9<span class="annotation">⦉@10</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="15:13-15:26: @15[0]: _1 = const 0_u32
+14:61-16:10: @15[1]: _10 = const ()"><span class="annotation">@15⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="15:13-15:26: @15[0]: _1 = const 0_u32
+14:61-16:10: @15[1]: _10 = const ()">            countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="15:13-15:26: @15[0]: _1 = const 0_u32
+14:61-16:10: @15[1]: _10 = const ()">        }<span class="annotation">⦉@15</span></span></span><span><span class="code odd" style="--layer: 1" title="16:10-16:10: @16[0]: _10 = const ()"><span class="annotation">@16⦊</span>‸<span class="annotation">⦉@16</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="17:9-17:23: @17[2]: _19 = CheckedSub(_1, const 5_u32)
+17:9-17:23: @18[0]: _1 = move (_19.0: u32)
+18:9-18:18: @18[1]: _4 = _1"><span class="annotation">@17,18⦊</span>countdown -= 5;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="17:9-17:23: @17[2]: _19 = CheckedSub(_1, const 5_u32)
+17:9-17:23: @18[0]: _1 = move (_19.0: u32)
+18:9-18:18: @18[1]: _4 = _1">        countdown<span class="annotation">⦉@17,18</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    } else {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="20:9-20:15: @8[0]: _0 = const ()"><span class="annotation">@8⦊</span>return<span class="annotation">⦉@8</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    };</span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="23:25-23:26: @21[3]: _21 = const 0_i32
-23:9-23:22: @21[4]: FakeRead(ForLet, _21)
-24:8-24:12: @21[7]: _23 = const true"><span class="annotation">@21⦊</span>mut countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="23:25-23:26: @21[3]: _21 = const 0_i32
-23:9-23:22: @21[4]: FakeRead(ForLet, _21)
-24:8-24:12: @21[7]: _23 = const true">    if true<span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="25:9-25:23: @22[0]: _21 = const 10_i32
-24:13-26:6: @22[1]: _22 = const ()"><span class="annotation">@22⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="25:9-25:23: @22[0]: _21 = const 10_i32
-24:13-26:6: @22[1]: _22 = const ()">        countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="25:9-25:23: @22[0]: _21 = const 10_i32
-24:13-26:6: @22[1]: _22 = const ()">    }<span class="annotation">⦉@22</span></span></span><span><span class="code even" style="--layer: 1" title="26:6-26:6: @23[0]: _22 = const ()"><span class="annotation">@23⦊</span>‸<span class="annotation">⦉@23</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="23:25-23:26: @19[3]: _21 = const 0_i32
+23:9-23:22: @19[4]: FakeRead(ForLet, _21)
+24:8-24:12: @19[7]: _23 = const true"><span class="annotation">@19⦊</span>mut countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="23:25-23:26: @19[3]: _21 = const 0_i32
+23:9-23:22: @19[4]: FakeRead(ForLet, _21)
+24:8-24:12: @19[7]: _23 = const true">    if true<span class="annotation">⦉@19</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="25:9-25:23: @20[0]: _21 = const 10_i32
+24:13-26:6: @20[1]: _22 = const ()"><span class="annotation">@20⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="25:9-25:23: @20[0]: _21 = const 10_i32
+24:13-26:6: @20[1]: _22 = const ()">        countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="25:9-25:23: @20[0]: _21 = const 10_i32
+24:13-26:6: @20[1]: _22 = const ()">    }<span class="annotation">⦉@20</span></span></span><span><span class="code even" style="--layer: 1" title="26:6-26:6: @21[0]: _22 = const ()"><span class="annotation">@21⦊</span>‸<span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code odd" style="--layer: 1" title="28:8-28:17: @24[5]: _26 = _21
-28:8-28:21: @24[6]: _25 = Gt(move _26, const 7_i32)"><span class="annotation">@24⦊</span>countdown &gt; 7<span class="annotation">⦉@24</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="29:9-29:23: @25[0]: _27 = CheckedSub(_21, const 4_i32)
-29:9-29:23: @27[0]: _21 = move (_27.0: i32)
-28:22-30:6: @27[1]: _24 = const ()"><span class="annotation">@25,27⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="29:9-29:23: @25[0]: _27 = CheckedSub(_21, const 4_i32)
-29:9-29:23: @27[0]: _21 = move (_27.0: i32)
-28:22-30:6: @27[1]: _24 = const ()">        countdown -= 4;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="29:9-29:23: @25[0]: _27 = CheckedSub(_21, const 4_i32)
-29:9-29:23: @27[0]: _21 = move (_27.0: i32)
-28:22-30:6: @27[1]: _24 = const ()">    }<span class="annotation">⦉@25,27</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code odd" style="--layer: 1" title="30:15-30:24: @26[2]: _29 = _21
-30:15-30:28: @26[3]: _28 = Gt(move _29, const 2_i32)"><span class="annotation">@26⦊</span>countdown &gt; 2<span class="annotation">⦉@26</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code even" style="--layer: 1" title="31:12-31:21: @28[5]: _34 = _21
-31:12-31:25: @28[6]: _33 = Lt(move _34, const 1_i32)"><span class="annotation">@28⦊</span>countdown &lt; 1<span class="annotation">⦉@28</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="31:29-31:38: @36[2]: _36 = _21
-31:29-31:42: @36[3]: _35 = Gt(move _36, const 5_i32)"><span class="annotation">@36⦊</span>countdown &gt; 5<span class="annotation">⦉@36</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="31:46-31:55: @32[2]: _38 = _21
-31:46-31:60: @32[3]: _37 = Ne(move _38, const 9_i32)"><span class="annotation">@32⦊</span>countdown != 9<span class="annotation">⦉@32</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="32:13-32:26: @38[0]: _21 = const 0_i32
-31:61-33:10: @38[1]: _30 = const ()"><span class="annotation">@38⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="32:13-32:26: @38[0]: _21 = const 0_i32
-31:61-33:10: @38[1]: _30 = const ()">            countdown = 0;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="32:13-32:26: @38[0]: _21 = const 0_i32
-31:61-33:10: @38[1]: _30 = const ()">        }<span class="annotation">⦉@38</span></span></span><span><span class="code even" style="--layer: 1" title="33:10-33:10: @39[0]: _30 = const ()"><span class="annotation">@39⦊</span>‸<span class="annotation">⦉@39</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="34:9-34:23: @40[2]: _39 = CheckedSub(_21, const 5_i32)
-34:9-34:23: @41[0]: _21 = move (_39.0: i32)"><span class="annotation">@40,41⦊</span>countdown -= 5<span class="annotation">⦉@40,41</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code odd" style="--layer: 1" title="28:8-28:17: @22[5]: _26 = _21
+28:8-28:21: @22[6]: _25 = Gt(move _26, const 7_i32)"><span class="annotation">@22⦊</span>countdown &gt; 7<span class="annotation">⦉@22</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="29:9-29:23: @23[0]: _27 = CheckedSub(_21, const 4_i32)
+29:9-29:23: @25[0]: _21 = move (_27.0: i32)
+28:22-30:6: @25[1]: _24 = const ()"><span class="annotation">@23,25⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="29:9-29:23: @23[0]: _27 = CheckedSub(_21, const 4_i32)
+29:9-29:23: @25[0]: _21 = move (_27.0: i32)
+28:22-30:6: @25[1]: _24 = const ()">        countdown -= 4;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="29:9-29:23: @23[0]: _27 = CheckedSub(_21, const 4_i32)
+29:9-29:23: @25[0]: _21 = move (_27.0: i32)
+28:22-30:6: @25[1]: _24 = const ()">    }<span class="annotation">⦉@23,25</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code odd" style="--layer: 1" title="30:15-30:24: @24[2]: _29 = _21
+30:15-30:28: @24[3]: _28 = Gt(move _29, const 2_i32)"><span class="annotation">@24⦊</span>countdown &gt; 2<span class="annotation">⦉@24</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code even" style="--layer: 1" title="31:12-31:21: @26[5]: _34 = _21
+31:12-31:25: @26[6]: _33 = Lt(move _34, const 1_i32)"><span class="annotation">@26⦊</span>countdown &lt; 1<span class="annotation">⦉@26</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="31:29-31:38: @32[2]: _36 = _21
+31:29-31:42: @32[3]: _35 = Gt(move _36, const 5_i32)"><span class="annotation">@32⦊</span>countdown &gt; 5<span class="annotation">⦉@32</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="31:46-31:55: @29[2]: _38 = _21
+31:46-31:60: @29[3]: _37 = Ne(move _38, const 9_i32)"><span class="annotation">@29⦊</span>countdown != 9<span class="annotation">⦉@29</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="32:13-32:26: @34[0]: _21 = const 0_i32
+31:61-33:10: @34[1]: _30 = const ()"><span class="annotation">@34⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="32:13-32:26: @34[0]: _21 = const 0_i32
+31:61-33:10: @34[1]: _30 = const ()">            countdown = 0;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="32:13-32:26: @34[0]: _21 = const 0_i32
+31:61-33:10: @34[1]: _30 = const ()">        }<span class="annotation">⦉@34</span></span></span><span><span class="code even" style="--layer: 1" title="33:10-33:10: @35[0]: _30 = const ()"><span class="annotation">@35⦊</span>‸<span class="annotation">⦉@35</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="34:9-34:23: @36[2]: _39 = CheckedSub(_21, const 5_i32)
+34:9-34:23: @37[0]: _21 = move (_39.0: i32)"><span class="annotation">@36,37⦊</span>countdown -= 5<span class="annotation">⦉@36,37</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    } else {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="36:9-36:15: @29[0]: _0 = const ()"><span class="annotation">@29⦊</span>return<span class="annotation">⦉@29</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="36:9-36:15: @27[0]: _0 = const ()"><span class="annotation">@27⦊</span>return<span class="annotation">⦉@27</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code odd" style="--layer: 1" title="39:8-39:12: @42[4]: _42 = const true"><span class="annotation">@42⦊</span>true<span class="annotation">⦉@42</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        let </span><span><span class="code even" style="--layer: 1" title="40:29-40:30: @43[1]: _43 = const 0_i32
-40:13-40:26: @43[2]: FakeRead(ForLet, _43)
-41:12-41:16: @43[5]: _45 = const true"><span class="annotation">@43⦊</span>mut countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="40:29-40:30: @43[1]: _43 = const 0_i32
-40:13-40:26: @43[2]: FakeRead(ForLet, _43)
-41:12-41:16: @43[5]: _45 = const true">        if true<span class="annotation">⦉@43</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="42:13-42:27: @45[0]: _43 = const 10_i32
-41:17-43:10: @45[1]: _44 = const ()"><span class="annotation">@45⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="42:13-42:27: @45[0]: _43 = const 10_i32
-41:17-43:10: @45[1]: _44 = const ()">            countdown = 10;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="42:13-42:27: @45[0]: _43 = const 10_i32
-41:17-43:10: @45[1]: _44 = const ()">        }<span class="annotation">⦉@45</span></span></span><span><span class="code even" style="--layer: 1" title="43:10-43:10: @46[0]: _44 = const ()"><span class="annotation">@46⦊</span>‸<span class="annotation">⦉@46</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code odd" style="--layer: 1" title="39:8-39:12: @38[4]: _42 = const true"><span class="annotation">@38⦊</span>true<span class="annotation">⦉@38</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        let </span><span><span class="code even" style="--layer: 1" title="40:29-40:30: @39[1]: _43 = const 0_i32
+40:13-40:26: @39[2]: FakeRead(ForLet, _43)
+41:12-41:16: @39[5]: _45 = const true"><span class="annotation">@39⦊</span>mut countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="40:29-40:30: @39[1]: _43 = const 0_i32
+40:13-40:26: @39[2]: FakeRead(ForLet, _43)
+41:12-41:16: @39[5]: _45 = const true">        if true<span class="annotation">⦉@39</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="42:13-42:27: @41[0]: _43 = const 10_i32
+41:17-43:10: @41[1]: _44 = const ()"><span class="annotation">@41⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="42:13-42:27: @41[0]: _43 = const 10_i32
+41:17-43:10: @41[1]: _44 = const ()">            countdown = 10;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="42:13-42:27: @41[0]: _43 = const 10_i32
+41:17-43:10: @41[1]: _44 = const ()">        }<span class="annotation">⦉@41</span></span></span><span><span class="code even" style="--layer: 1" title="43:10-43:10: @42[0]: _44 = const ()"><span class="annotation">@42⦊</span>‸<span class="annotation">⦉@42</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code odd" style="--layer: 1" title="45:12-45:21: @47[4]: _47 = _43
-45:12-45:25: @47[5]: _46 = Gt(move _47, const 7_i32)"><span class="annotation">@47⦊</span>countdown &gt; 7<span class="annotation">⦉@47</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="46:13-46:27: @48[0]: _48 = CheckedSub(_43, const 4_i32)
-46:13-46:27: @50[0]: _43 = move (_48.0: i32)
-45:26-47:10: @50[1]: _41 = const ()"><span class="annotation">@48,50⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="46:13-46:27: @48[0]: _48 = CheckedSub(_43, const 4_i32)
-46:13-46:27: @50[0]: _43 = move (_48.0: i32)
-45:26-47:10: @50[1]: _41 = const ()">            countdown -= 4;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="46:13-46:27: @48[0]: _48 = CheckedSub(_43, const 4_i32)
-46:13-46:27: @50[0]: _43 = move (_48.0: i32)
-45:26-47:10: @50[1]: _41 = const ()">        }<span class="annotation">⦉@48,50</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        else if </span><span><span class="code odd" style="--layer: 1" title="48:17-48:26: @49[2]: _50 = _43
-48:17-48:30: @49[3]: _49 = Gt(move _50, const 2_i32)"><span class="annotation">@49⦊</span>countdown &gt; 2<span class="annotation">⦉@49</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">            if </span><span><span class="code even" style="--layer: 1" title="49:16-49:25: @51[5]: _55 = _43
-49:16-49:29: @51[6]: _54 = Lt(move _55, const 1_i32)"><span class="annotation">@51⦊</span>countdown &lt; 1<span class="annotation">⦉@51</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="49:33-49:42: @59[2]: _57 = _43
-49:33-49:46: @59[3]: _56 = Gt(move _57, const 5_i32)"><span class="annotation">@59⦊</span>countdown &gt; 5<span class="annotation">⦉@59</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="49:50-49:59: @55[2]: _59 = _43
-49:50-49:64: @55[3]: _58 = Ne(move _59, const 9_i32)"><span class="annotation">@55⦊</span>countdown != 9<span class="annotation">⦉@55</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="50:17-50:30: @61[0]: _43 = const 0_i32
-49:65-51:14: @61[1]: _51 = const ()"><span class="annotation">@61⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="50:17-50:30: @61[0]: _43 = const 0_i32
-49:65-51:14: @61[1]: _51 = const ()">                countdown = 0;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="50:17-50:30: @61[0]: _43 = const 0_i32
-49:65-51:14: @61[1]: _51 = const ()">            }<span class="annotation">⦉@61</span></span></span><span><span class="code even" style="--layer: 1" title="51:14-51:14: @62[0]: _51 = const ()"><span class="annotation">@62⦊</span>‸<span class="annotation">⦉@62</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="52:13-52:27: @63[2]: _60 = CheckedSub(_43, const 5_i32)
-52:13-52:27: @64[0]: _43 = move (_60.0: i32)"><span class="annotation">@63,64⦊</span>countdown -= 5<span class="annotation">⦉@63,64</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code odd" style="--layer: 1" title="45:12-45:21: @43[4]: _47 = _43
+45:12-45:25: @43[5]: _46 = Gt(move _47, const 7_i32)"><span class="annotation">@43⦊</span>countdown &gt; 7<span class="annotation">⦉@43</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="46:13-46:27: @44[0]: _48 = CheckedSub(_43, const 4_i32)
+46:13-46:27: @46[0]: _43 = move (_48.0: i32)
+45:26-47:10: @46[1]: _41 = const ()"><span class="annotation">@44,46⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="46:13-46:27: @44[0]: _48 = CheckedSub(_43, const 4_i32)
+46:13-46:27: @46[0]: _43 = move (_48.0: i32)
+45:26-47:10: @46[1]: _41 = const ()">            countdown -= 4;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="46:13-46:27: @44[0]: _48 = CheckedSub(_43, const 4_i32)
+46:13-46:27: @46[0]: _43 = move (_48.0: i32)
+45:26-47:10: @46[1]: _41 = const ()">        }<span class="annotation">⦉@44,46</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        else if </span><span><span class="code odd" style="--layer: 1" title="48:17-48:26: @45[2]: _50 = _43
+48:17-48:30: @45[3]: _49 = Gt(move _50, const 2_i32)"><span class="annotation">@45⦊</span>countdown &gt; 2<span class="annotation">⦉@45</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">            if </span><span><span class="code even" style="--layer: 1" title="49:16-49:25: @47[5]: _55 = _43
+49:16-49:29: @47[6]: _54 = Lt(move _55, const 1_i32)"><span class="annotation">@47⦊</span>countdown &lt; 1<span class="annotation">⦉@47</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="49:33-49:42: @53[2]: _57 = _43
+49:33-49:46: @53[3]: _56 = Gt(move _57, const 5_i32)"><span class="annotation">@53⦊</span>countdown &gt; 5<span class="annotation">⦉@53</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="49:50-49:59: @50[2]: _59 = _43
+49:50-49:64: @50[3]: _58 = Ne(move _59, const 9_i32)"><span class="annotation">@50⦊</span>countdown != 9<span class="annotation">⦉@50</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="50:17-50:30: @55[0]: _43 = const 0_i32
+49:65-51:14: @55[1]: _51 = const ()"><span class="annotation">@55⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="50:17-50:30: @55[0]: _43 = const 0_i32
+49:65-51:14: @55[1]: _51 = const ()">                countdown = 0;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="50:17-50:30: @55[0]: _43 = const 0_i32
+49:65-51:14: @55[1]: _51 = const ()">            }<span class="annotation">⦉@55</span></span></span><span><span class="code even" style="--layer: 1" title="51:14-51:14: @56[0]: _51 = const ()"><span class="annotation">@56⦊</span>‸<span class="annotation">⦉@56</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="52:13-52:27: @57[2]: _60 = CheckedSub(_43, const 5_i32)
+52:13-52:27: @58[0]: _43 = move (_60.0: i32)"><span class="annotation">@57,58⦊</span>countdown -= 5<span class="annotation">⦉@57,58</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">        } else {</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="54:13-54:19: @52[0]: _0 = const ()"><span class="annotation">@52⦊</span>return<span class="annotation">⦉@52</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="54:13-54:19: @48[0]: _0 = const ()"><span class="annotation">@48⦊</span>return<span class="annotation">⦉@48</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">        }</span></span>
-<span class="line"><span class="code" style="--layer: 0">    }</span><span><span class="code odd" style="--layer: 1" title="56:6-56:6: @44[0]: _41 = const ()"><span class="annotation">@44⦊</span>‸<span class="annotation">⦉@44</span></span></span><span class="code" style="--layer: 0"> // Note: closing brace shows uncovered (vs. `0` for implicit else) because condition literal</span></span>
+<span class="line"><span class="code" style="--layer: 0">    }</span><span><span class="code odd" style="--layer: 1" title="56:6-56:6: @40[0]: _41 = const ()"><span class="annotation">@40⦊</span>‸<span class="annotation">⦉@40</span></span></span><span class="code" style="--layer: 0"> // Note: closing brace shows uncovered (vs. `0` for implicit else) because condition literal</span></span>
 <span class="line"><span class="code" style="--layer: 0">      // `true` was const-evaluated. The compiler knows the `if` block will be executed.</span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="59:25-59:26: @66[3]: _62 = const 0_i32
-59:9-59:22: @66[4]: FakeRead(ForLet, _62)
-60:8-60:12: @66[7]: _64 = const true"><span class="annotation">@66⦊</span>mut countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="59:25-59:26: @66[3]: _62 = const 0_i32
-59:9-59:22: @66[4]: FakeRead(ForLet, _62)
-60:8-60:12: @66[7]: _64 = const true">    if true<span class="annotation">⦉@66</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="61:9-61:22: @67[0]: _62 = const 1_i32
-60:13-62:6: @67[1]: _63 = const ()"><span class="annotation">@67⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="61:9-61:22: @67[0]: _62 = const 1_i32
-60:13-62:6: @67[1]: _63 = const ()">        countdown = 1;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="61:9-61:22: @67[0]: _62 = const 1_i32
-60:13-62:6: @67[1]: _63 = const ()">    }<span class="annotation">⦉@67</span></span></span><span><span class="code even" style="--layer: 1" title="62:6-62:6: @68[0]: _63 = const ()"><span class="annotation">@68⦊</span>‸<span class="annotation">⦉@68</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="59:25-59:26: @60[3]: _62 = const 0_i32
+59:9-59:22: @60[4]: FakeRead(ForLet, _62)
+60:8-60:12: @60[7]: _64 = const true"><span class="annotation">@60⦊</span>mut countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="59:25-59:26: @60[3]: _62 = const 0_i32
+59:9-59:22: @60[4]: FakeRead(ForLet, _62)
+60:8-60:12: @60[7]: _64 = const true">    if true<span class="annotation">⦉@60</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="61:9-61:22: @61[0]: _62 = const 1_i32
+60:13-62:6: @61[1]: _63 = const ()"><span class="annotation">@61⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="61:9-61:22: @61[0]: _62 = const 1_i32
+60:13-62:6: @61[1]: _63 = const ()">        countdown = 1;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="61:9-61:22: @61[0]: _62 = const 1_i32
+60:13-62:6: @61[1]: _63 = const ()">    }<span class="annotation">⦉@61</span></span></span><span><span class="code even" style="--layer: 1" title="62:6-62:6: @62[0]: _63 = const ()"><span class="annotation">@62⦊</span>‸<span class="annotation">⦉@62</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code odd" style="--layer: 1" title="64:9-64:10: @89[1]: FakeRead(ForLet, _65)"><span class="annotation">@89⦊</span>z<span class="annotation">⦉@89</span></span></span><span class="code" style="--layer: 0"> = if </span><span><span class="code even" style="--layer: 1" title="64:16-64:25: @69[5]: _67 = _62
-64:16-64:29: @69[6]: _66 = Gt(move _67, const 7_i32)"><span class="annotation">@69⦊</span>countdown &gt; 7<span class="annotation">⦉@69</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="65:9-65:23: @70[0]: _68 = CheckedSub(_62, const 4_i32)
-65:9-65:23: @72[0]: _62 = move (_68.0: i32)
-64:30-66:6: @72[1]: _65 = const ()"><span class="annotation">@70,72⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="65:9-65:23: @70[0]: _68 = CheckedSub(_62, const 4_i32)
-65:9-65:23: @72[0]: _62 = move (_68.0: i32)
-64:30-66:6: @72[1]: _65 = const ()">        countdown -= 4;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="65:9-65:23: @70[0]: _68 = CheckedSub(_62, const 4_i32)
-65:9-65:23: @72[0]: _62 = move (_68.0: i32)
-64:30-66:6: @72[1]: _65 = const ()">    }<span class="annotation">⦉@70,72</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code even" style="--layer: 1" title="66:15-66:24: @71[2]: _70 = _62
-66:15-66:28: @71[3]: _69 = Gt(move _70, const 2_i32)"><span class="annotation">@71⦊</span>countdown &gt; 2<span class="annotation">⦉@71</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code odd" style="--layer: 1" title="67:12-67:21: @73[5]: _75 = _62
-67:12-67:25: @73[6]: _74 = Lt(move _75, const 1_i32)"><span class="annotation">@73⦊</span>countdown &lt; 1<span class="annotation">⦉@73</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="67:29-67:38: @81[2]: _77 = _62
-67:29-67:42: @81[3]: _76 = Gt(move _77, const 5_i32)"><span class="annotation">@81⦊</span>countdown &gt; 5<span class="annotation">⦉@81</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="67:46-67:55: @77[2]: _79 = _62
-67:46-67:60: @77[3]: _78 = Ne(move _79, const 9_i32)"><span class="annotation">@77⦊</span>countdown != 9<span class="annotation">⦉@77</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="68:13-68:26: @83[0]: _62 = const 0_i32
-67:61-69:10: @83[1]: _71 = const ()"><span class="annotation">@83⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="68:13-68:26: @83[0]: _62 = const 0_i32
-67:61-69:10: @83[1]: _71 = const ()">            countdown = 0;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="68:13-68:26: @83[0]: _62 = const 0_i32
-67:61-69:10: @83[1]: _71 = const ()">        }<span class="annotation">⦉@83</span></span></span><span><span class="code odd" style="--layer: 1" title="69:10-69:10: @84[0]: _71 = const ()"><span class="annotation">@84⦊</span>‸<span class="annotation">⦉@84</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="70:9-70:23: @85[2]: _80 = CheckedSub(_62, const 5_i32)
-70:9-70:23: @86[0]: _62 = move (_80.0: i32)"><span class="annotation">@85,86⦊</span>countdown -= 5<span class="annotation">⦉@85,86</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code odd" style="--layer: 1" title="64:9-64:10: @81[1]: FakeRead(ForLet, _65)"><span class="annotation">@81⦊</span>z<span class="annotation">⦉@81</span></span></span><span class="code" style="--layer: 0"> = if </span><span><span class="code even" style="--layer: 1" title="64:16-64:25: @63[5]: _67 = _62
+64:16-64:29: @63[6]: _66 = Gt(move _67, const 7_i32)"><span class="annotation">@63⦊</span>countdown &gt; 7<span class="annotation">⦉@63</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="65:9-65:23: @64[0]: _68 = CheckedSub(_62, const 4_i32)
+65:9-65:23: @66[0]: _62 = move (_68.0: i32)
+64:30-66:6: @66[1]: _65 = const ()"><span class="annotation">@64,66⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="65:9-65:23: @64[0]: _68 = CheckedSub(_62, const 4_i32)
+65:9-65:23: @66[0]: _62 = move (_68.0: i32)
+64:30-66:6: @66[1]: _65 = const ()">        countdown -= 4;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="65:9-65:23: @64[0]: _68 = CheckedSub(_62, const 4_i32)
+65:9-65:23: @66[0]: _62 = move (_68.0: i32)
+64:30-66:6: @66[1]: _65 = const ()">    }<span class="annotation">⦉@64,66</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code even" style="--layer: 1" title="66:15-66:24: @65[2]: _70 = _62
+66:15-66:28: @65[3]: _69 = Gt(move _70, const 2_i32)"><span class="annotation">@65⦊</span>countdown &gt; 2<span class="annotation">⦉@65</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code odd" style="--layer: 1" title="67:12-67:21: @67[5]: _75 = _62
+67:12-67:25: @67[6]: _74 = Lt(move _75, const 1_i32)"><span class="annotation">@67⦊</span>countdown &lt; 1<span class="annotation">⦉@67</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="67:29-67:38: @73[2]: _77 = _62
+67:29-67:42: @73[3]: _76 = Gt(move _77, const 5_i32)"><span class="annotation">@73⦊</span>countdown &gt; 5<span class="annotation">⦉@73</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="67:46-67:55: @70[2]: _79 = _62
+67:46-67:60: @70[3]: _78 = Ne(move _79, const 9_i32)"><span class="annotation">@70⦊</span>countdown != 9<span class="annotation">⦉@70</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="68:13-68:26: @75[0]: _62 = const 0_i32
+67:61-69:10: @75[1]: _71 = const ()"><span class="annotation">@75⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="68:13-68:26: @75[0]: _62 = const 0_i32
+67:61-69:10: @75[1]: _71 = const ()">            countdown = 0;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="68:13-68:26: @75[0]: _62 = const 0_i32
+67:61-69:10: @75[1]: _71 = const ()">        }<span class="annotation">⦉@75</span></span></span><span><span class="code odd" style="--layer: 1" title="69:10-69:10: @76[0]: _71 = const ()"><span class="annotation">@76⦊</span>‸<span class="annotation">⦉@76</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="70:9-70:23: @77[2]: _80 = CheckedSub(_62, const 5_i32)
+70:9-70:23: @78[0]: _62 = move (_80.0: i32)"><span class="annotation">@77,78⦊</span>countdown -= 5<span class="annotation">⦉@77,78</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    } else {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        let </span><span><span class="code odd" style="--layer: 1" title="72:35-72:44: @74[1]: _82 = _62
-72:13-72:32: @74[2]: FakeRead(ForLet, _82)
-73:18-73:27: @74[9]: _113 = const main::promoted[1]
-73:18-73:27: @74[10]: _88 = &amp;(*_113)
-73:18-73:27: @74[11]: _87 = &amp;(*_88)
-73:18-73:27: @74[12]: _86 = move _87 as &amp;[&amp;str] (Pointer(Unsize))
-73:9-73:29: @74[18]: _94 = ()
-73:9-73:29: @74[19]: FakeRead(ForMatchedPlace, _94)
-73:9-73:29: @74[20]: _112 = const main::promoted[0]
-73:9-73:29: @74[21]: _92 = &amp;(*_112)
-73:9-73:29: @74[22]: _91 = &amp;(*_92)
-73:9-73:29: @74[23]: _90 = move _91 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-73:9-73:29: @74.Call: _85 = std::fmt::Arguments::new_v1(move _86, move _90) -&gt; [return: bb87, unwind: bb112]
-73:9-73:29: @87.Call: _84 = std::io::_print(move _85) -&gt; [return: bb88, unwind: bb112]
-73:9-73:29: @88[5]: _83 = const ()
-74:9-74:15: @88[7]: _0 = const ()"><span class="annotation">@74,87,88⦊</span>should_be_reachable = countdown;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="72:35-72:44: @74[1]: _82 = _62
-72:13-72:32: @74[2]: FakeRead(ForLet, _82)
-73:18-73:27: @74[9]: _113 = const main::promoted[1]
-73:18-73:27: @74[10]: _88 = &amp;(*_113)
-73:18-73:27: @74[11]: _87 = &amp;(*_88)
-73:18-73:27: @74[12]: _86 = move _87 as &amp;[&amp;str] (Pointer(Unsize))
-73:9-73:29: @74[18]: _94 = ()
-73:9-73:29: @74[19]: FakeRead(ForMatchedPlace, _94)
-73:9-73:29: @74[20]: _112 = const main::promoted[0]
-73:9-73:29: @74[21]: _92 = &amp;(*_112)
-73:9-73:29: @74[22]: _91 = &amp;(*_92)
-73:9-73:29: @74[23]: _90 = move _91 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-73:9-73:29: @74.Call: _85 = std::fmt::Arguments::new_v1(move _86, move _90) -&gt; [return: bb87, unwind: bb112]
-73:9-73:29: @87.Call: _84 = std::io::_print(move _85) -&gt; [return: bb88, unwind: bb112]
-73:9-73:29: @88[5]: _83 = const ()
-74:9-74:15: @88[7]: _0 = const ()">        println!("reached");</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="72:35-72:44: @74[1]: _82 = _62
-72:13-72:32: @74[2]: FakeRead(ForLet, _82)
-73:18-73:27: @74[9]: _113 = const main::promoted[1]
-73:18-73:27: @74[10]: _88 = &amp;(*_113)
-73:18-73:27: @74[11]: _87 = &amp;(*_88)
-73:18-73:27: @74[12]: _86 = move _87 as &amp;[&amp;str] (Pointer(Unsize))
-73:9-73:29: @74[18]: _94 = ()
-73:9-73:29: @74[19]: FakeRead(ForMatchedPlace, _94)
-73:9-73:29: @74[20]: _112 = const main::promoted[0]
-73:9-73:29: @74[21]: _92 = &amp;(*_112)
-73:9-73:29: @74[22]: _91 = &amp;(*_92)
-73:9-73:29: @74[23]: _90 = move _91 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-73:9-73:29: @74.Call: _85 = std::fmt::Arguments::new_v1(move _86, move _90) -&gt; [return: bb87, unwind: bb112]
-73:9-73:29: @87.Call: _84 = std::io::_print(move _85) -&gt; [return: bb88, unwind: bb112]
-73:9-73:29: @88[5]: _83 = const ()
-74:9-74:15: @88[7]: _0 = const ()">        return<span class="annotation">⦉@74,87,88</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">        let </span><span><span class="code odd" style="--layer: 1" title="72:35-72:44: @68[1]: _82 = _62
+72:13-72:32: @68[2]: FakeRead(ForLet, _82)
+73:18-73:27: @68[9]: _113 = const main::promoted[1]
+73:18-73:27: @68[10]: _88 = &amp;(*_113)
+73:18-73:27: @68[11]: _87 = &amp;(*_88)
+73:18-73:27: @68[12]: _86 = move _87 as &amp;[&amp;str] (Pointer(Unsize))
+73:9-73:29: @68[18]: _94 = ()
+73:9-73:29: @68[19]: FakeRead(ForMatchedPlace, _94)
+73:9-73:29: @68[20]: _112 = const main::promoted[0]
+73:9-73:29: @68[21]: _92 = &amp;(*_112)
+73:9-73:29: @68[22]: _91 = &amp;(*_92)
+73:9-73:29: @68[23]: _90 = move _91 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+73:9-73:29: @68.Call: _85 = std::fmt::Arguments::new_v1(move _86, move _90) -&gt; [return: bb79, unwind: bb102]
+73:9-73:29: @79.Call: _84 = std::io::_print(move _85) -&gt; [return: bb80, unwind: bb102]
+73:9-73:29: @80[5]: _83 = const ()
+74:9-74:15: @80[7]: _0 = const ()"><span class="annotation">@68,79,80⦊</span>should_be_reachable = countdown;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="72:35-72:44: @68[1]: _82 = _62
+72:13-72:32: @68[2]: FakeRead(ForLet, _82)
+73:18-73:27: @68[9]: _113 = const main::promoted[1]
+73:18-73:27: @68[10]: _88 = &amp;(*_113)
+73:18-73:27: @68[11]: _87 = &amp;(*_88)
+73:18-73:27: @68[12]: _86 = move _87 as &amp;[&amp;str] (Pointer(Unsize))
+73:9-73:29: @68[18]: _94 = ()
+73:9-73:29: @68[19]: FakeRead(ForMatchedPlace, _94)
+73:9-73:29: @68[20]: _112 = const main::promoted[0]
+73:9-73:29: @68[21]: _92 = &amp;(*_112)
+73:9-73:29: @68[22]: _91 = &amp;(*_92)
+73:9-73:29: @68[23]: _90 = move _91 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+73:9-73:29: @68.Call: _85 = std::fmt::Arguments::new_v1(move _86, move _90) -&gt; [return: bb79, unwind: bb102]
+73:9-73:29: @79.Call: _84 = std::io::_print(move _85) -&gt; [return: bb80, unwind: bb102]
+73:9-73:29: @80[5]: _83 = const ()
+74:9-74:15: @80[7]: _0 = const ()">        println!("reached");</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="72:35-72:44: @68[1]: _82 = _62
+72:13-72:32: @68[2]: FakeRead(ForLet, _82)
+73:18-73:27: @68[9]: _113 = const main::promoted[1]
+73:18-73:27: @68[10]: _88 = &amp;(*_113)
+73:18-73:27: @68[11]: _87 = &amp;(*_88)
+73:18-73:27: @68[12]: _86 = move _87 as &amp;[&amp;str] (Pointer(Unsize))
+73:9-73:29: @68[18]: _94 = ()
+73:9-73:29: @68[19]: FakeRead(ForMatchedPlace, _94)
+73:9-73:29: @68[20]: _112 = const main::promoted[0]
+73:9-73:29: @68[21]: _92 = &amp;(*_112)
+73:9-73:29: @68[22]: _91 = &amp;(*_92)
+73:9-73:29: @68[23]: _90 = move _91 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+73:9-73:29: @68.Call: _85 = std::fmt::Arguments::new_v1(move _86, move _90) -&gt; [return: bb79, unwind: bb102]
+73:9-73:29: @79.Call: _84 = std::io::_print(move _85) -&gt; [return: bb80, unwind: bb102]
+73:9-73:29: @80[5]: _83 = const ()
+74:9-74:15: @80[7]: _0 = const ()">        return<span class="annotation">⦉@68,79,80</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    };</span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="77:9-77:10: @107[1]: FakeRead(ForLet, _95)"><span class="annotation">@107⦊</span>w<span class="annotation">⦉@107</span></span></span><span class="code" style="--layer: 0"> = if </span><span><span class="code odd" style="--layer: 1" title="77:16-77:25: @89[5]: _97 = _62
-77:16-77:29: @89[6]: _96 = Gt(move _97, const 7_i32)"><span class="annotation">@89⦊</span>countdown &gt; 7<span class="annotation">⦉@89</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="78:9-78:23: @90[0]: _98 = CheckedSub(_62, const 4_i32)
-78:9-78:23: @92[0]: _62 = move (_98.0: i32)
-77:30-79:6: @92[1]: _95 = const ()"><span class="annotation">@90,92⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="78:9-78:23: @90[0]: _98 = CheckedSub(_62, const 4_i32)
-78:9-78:23: @92[0]: _62 = move (_98.0: i32)
-77:30-79:6: @92[1]: _95 = const ()">        countdown -= 4;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="78:9-78:23: @90[0]: _98 = CheckedSub(_62, const 4_i32)
-78:9-78:23: @92[0]: _62 = move (_98.0: i32)
-77:30-79:6: @92[1]: _95 = const ()">    }<span class="annotation">⦉@90,92</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code odd" style="--layer: 1" title="79:15-79:24: @91[2]: _100 = _62
-79:15-79:28: @91[3]: _99 = Gt(move _100, const 2_i32)"><span class="annotation">@91⦊</span>countdown &gt; 2<span class="annotation">⦉@91</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code even" style="--layer: 1" title="80:12-80:21: @93[5]: _105 = _62
-80:12-80:25: @93[6]: _104 = Lt(move _105, const 1_i32)"><span class="annotation">@93⦊</span>countdown &lt; 1<span class="annotation">⦉@93</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="80:29-80:38: @101[2]: _107 = _62
-80:29-80:42: @101[3]: _106 = Gt(move _107, const 5_i32)"><span class="annotation">@101⦊</span>countdown &gt; 5<span class="annotation">⦉@101</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="80:46-80:55: @97[2]: _109 = _62
-80:46-80:60: @97[3]: _108 = Ne(move _109, const 9_i32)"><span class="annotation">@97⦊</span>countdown != 9<span class="annotation">⦉@97</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="81:13-81:26: @103[0]: _62 = const 0_i32
-80:61-82:10: @103[1]: _101 = const ()"><span class="annotation">@103⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="81:13-81:26: @103[0]: _62 = const 0_i32
-80:61-82:10: @103[1]: _101 = const ()">            countdown = 0;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="81:13-81:26: @103[0]: _62 = const 0_i32
-80:61-82:10: @103[1]: _101 = const ()">        }<span class="annotation">⦉@103</span></span></span><span><span class="code even" style="--layer: 1" title="82:10-82:10: @104[0]: _101 = const ()"><span class="annotation">@104⦊</span>‸<span class="annotation">⦉@104</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="83:9-83:23: @105[2]: _110 = CheckedSub(_62, const 5_i32)
-83:9-83:23: @106[0]: _62 = move (_110.0: i32)"><span class="annotation">@105,106⦊</span>countdown -= 5<span class="annotation">⦉@105,106</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="77:9-77:10: @97[1]: FakeRead(ForLet, _95)"><span class="annotation">@97⦊</span>w<span class="annotation">⦉@97</span></span></span><span class="code" style="--layer: 0"> = if </span><span><span class="code odd" style="--layer: 1" title="77:16-77:25: @81[5]: _97 = _62
+77:16-77:29: @81[6]: _96 = Gt(move _97, const 7_i32)"><span class="annotation">@81⦊</span>countdown &gt; 7<span class="annotation">⦉@81</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="78:9-78:23: @82[0]: _98 = CheckedSub(_62, const 4_i32)
+78:9-78:23: @84[0]: _62 = move (_98.0: i32)
+77:30-79:6: @84[1]: _95 = const ()"><span class="annotation">@82,84⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="78:9-78:23: @82[0]: _98 = CheckedSub(_62, const 4_i32)
+78:9-78:23: @84[0]: _62 = move (_98.0: i32)
+77:30-79:6: @84[1]: _95 = const ()">        countdown -= 4;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="78:9-78:23: @82[0]: _98 = CheckedSub(_62, const 4_i32)
+78:9-78:23: @84[0]: _62 = move (_98.0: i32)
+77:30-79:6: @84[1]: _95 = const ()">    }<span class="annotation">⦉@82,84</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code odd" style="--layer: 1" title="79:15-79:24: @83[2]: _100 = _62
+79:15-79:28: @83[3]: _99 = Gt(move _100, const 2_i32)"><span class="annotation">@83⦊</span>countdown &gt; 2<span class="annotation">⦉@83</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        if </span><span><span class="code even" style="--layer: 1" title="80:12-80:21: @85[5]: _105 = _62
+80:12-80:25: @85[6]: _104 = Lt(move _105, const 1_i32)"><span class="annotation">@85⦊</span>countdown &lt; 1<span class="annotation">⦉@85</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="80:29-80:38: @91[2]: _107 = _62
+80:29-80:42: @91[3]: _106 = Gt(move _107, const 5_i32)"><span class="annotation">@91⦊</span>countdown &gt; 5<span class="annotation">⦉@91</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code even" style="--layer: 1" title="80:46-80:55: @88[2]: _109 = _62
+80:46-80:60: @88[3]: _108 = Ne(move _109, const 9_i32)"><span class="annotation">@88⦊</span>countdown != 9<span class="annotation">⦉@88</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="81:13-81:26: @93[0]: _62 = const 0_i32
+80:61-82:10: @93[1]: _101 = const ()"><span class="annotation">@93⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="81:13-81:26: @93[0]: _62 = const 0_i32
+80:61-82:10: @93[1]: _101 = const ()">            countdown = 0;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="81:13-81:26: @93[0]: _62 = const 0_i32
+80:61-82:10: @93[1]: _101 = const ()">        }<span class="annotation">⦉@93</span></span></span><span><span class="code even" style="--layer: 1" title="82:10-82:10: @94[0]: _101 = const ()"><span class="annotation">@94⦊</span>‸<span class="annotation">⦉@94</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="83:9-83:23: @95[2]: _110 = CheckedSub(_62, const 5_i32)
+83:9-83:23: @96[0]: _62 = move (_110.0: i32)"><span class="annotation">@95,96⦊</span>countdown -= 5<span class="annotation">⦉@95,96</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    } else {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="85:9-85:15: @94[0]: _0 = const ()"><span class="annotation">@94⦊</span>return<span class="annotation">⦉@94</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="85:9-85:15: @86[0]: _0 = const ()"><span class="annotation">@86⦊</span>return<span class="annotation">⦉@86</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    };</span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="87:2-87:2: @111.Return: return"><span class="annotation">@111⦊</span>‸<span class="annotation">⦉@111</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="87:2-87:2: @101.Return: return"><span class="annotation">@101⦊</span>‸<span class="annotation">⦉@101</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html
index 358e2e2bbba..a6f8d500065 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html
@@ -69,9 +69,9 @@ For revisions in Pull Requests (PR):
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb36]
+<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb32]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
+7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb31]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
@@ -79,9 +79,9 @@ For revisions in Pull Requests (PR):
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
 10:8-10:15: @3[12]: _10 = _1"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb36]
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb32]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
+7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb31]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
@@ -89,9 +89,9 @@ For revisions in Pull Requests (PR):
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
 10:8-10:15: @3[12]: _10 = _1">    // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb36]
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb32]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
+7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb31]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
@@ -99,9 +99,9 @@ For revisions in Pull Requests (PR):
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
 10:8-10:15: @3[12]: _10 = _1">    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb36]
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb32]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
+7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb31]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
@@ -109,9 +109,9 @@ For revisions in Pull Requests (PR):
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
 10:8-10:15: @3[12]: _10 = _1">    // dependent conditions.</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb36]
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb32]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
+7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb31]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
@@ -119,9 +119,9 @@ For revisions in Pull Requests (PR):
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
 10:8-10:15: @3[12]: _10 = _1">    let is_true = std::env::args().len() == 1;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb36]
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb32]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
+7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb31]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
@@ -129,9 +129,9 @@ For revisions in Pull Requests (PR):
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
 10:8-10:15: @3[12]: _10 = _1"></span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb36]
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb32]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
+7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb31]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
@@ -139,9 +139,9 @@ For revisions in Pull Requests (PR):
 9:17-9:22: @3[6]: _6 = (_8.1: i32)
 9:24-9:29: @3[8]: _7 = (_8.2: i32)
 10:8-10:15: @3[12]: _10 = _1">    let (mut a, mut b, mut c) = (0, 0, 0);</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb36]
+<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = std::env::args() -&gt; [return: bb1, unwind: bb32]
 7:19-7:35: @1[0]: _3 = &amp;_4
-7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb35]
+7:19-7:41: @1.Call: _2 = &lt;std::env::Args as std::iter::ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb31]
 7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
 7:9-7:16: @2[3]: FakeRead(ForLet, _1)
 9:33-9:42: @3[2]: _8 = (const 0_i32, const 0_i32, const 0_i32)
@@ -169,91 +169,91 @@ For revisions in Pull Requests (PR):
 13:9-13:16: @4[2]: _7 = const 100_i32
 10:16-14:6: @4[3]: _9 = const ()">    }<span class="annotation">⦉@4</span></span></span><span><span class="code even" style="--layer: 1" title="14:6-14:6: @5[0]: _9 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    let</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="16:9-16:17: @10[2]: FakeRead(ForLet, _11)"><span class="annotation">@10⦊</span>somebool<span class="annotation">⦉@10</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="16:9-16:17: @9[2]: FakeRead(ForLet, _11)"><span class="annotation">@9⦊</span>somebool<span class="annotation">⦉@9</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        =</span></span>
 <span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="18:13-18:14: @6[5]: _13 = _5
 18:17-18:18: @6[7]: _14 = _6
 18:13-18:18: @6[8]: _12 = Lt(move _13, move _14)"><span class="annotation">@6⦊</span>a &lt; b<span class="annotation">⦉@6</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        ||</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="20:13-20:14: @9[2]: _16 = _6
-20:17-20:18: @9[4]: _17 = _7
-20:13-20:18: @9[5]: _15 = Lt(move _16, move _17)"><span class="annotation">@9⦊</span>b &lt; c<span class="annotation">⦉@9</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="20:13-20:14: @8[2]: _16 = _6
+20:17-20:18: @8[4]: _17 = _7
+20:13-20:18: @8[5]: _15 = Lt(move _16, move _17)"><span class="annotation">@8⦊</span>b &lt; c<span class="annotation">⦉@8</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    ;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    let</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="23:9-23:17: @14[2]: FakeRead(ForLet, _18)"><span class="annotation">@14⦊</span>somebool<span class="annotation">⦉@14</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="23:9-23:17: @12[2]: FakeRead(ForLet, _18)"><span class="annotation">@12⦊</span>somebool<span class="annotation">⦉@12</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        =</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="25:13-25:14: @10[6]: _20 = _6
-25:17-25:18: @10[8]: _21 = _5
-25:13-25:18: @10[9]: _19 = Lt(move _20, move _21)"><span class="annotation">@10⦊</span>b &lt; a<span class="annotation">⦉@10</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code odd" style="--layer: 1" title="25:13-25:14: @9[6]: _20 = _6
+25:17-25:18: @9[8]: _21 = _5
+25:13-25:18: @9[9]: _19 = Lt(move _20, move _21)"><span class="annotation">@9⦊</span>b &lt; a<span class="annotation">⦉@9</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">        ||</span></span>
-<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="27:13-27:14: @13[2]: _23 = _6
-27:17-27:18: @13[4]: _24 = _7
-27:13-27:18: @13[5]: _22 = Lt(move _23, move _24)"><span class="annotation">@13⦊</span>b &lt; c<span class="annotation">⦉@13</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">            </span><span><span class="code even" style="--layer: 1" title="27:13-27:14: @11[2]: _23 = _6
+27:17-27:18: @11[4]: _24 = _7
+27:13-27:18: @11[5]: _22 = Lt(move _23, move _24)"><span class="annotation">@11⦊</span>b &lt; c<span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    ;</span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code odd" style="--layer: 1" title="29:9-29:17: @18[2]: FakeRead(ForLet, _25)"><span class="annotation">@18⦊</span>somebool<span class="annotation">⦉@18</span></span></span><span class="code" style="--layer: 0"> = </span><span><span class="code even" style="--layer: 1" title="29:20-29:21: @14[6]: _27 = _5
-29:24-29:25: @14[8]: _28 = _6
-29:20-29:25: @14[9]: _26 = Lt(move _27, move _28)"><span class="annotation">@14⦊</span>a &lt; b<span class="annotation">⦉@14</span></span></span><span class="code" style="--layer: 0"> &amp;&amp; </span><span><span class="code odd" style="--layer: 1" title="29:29-29:30: @17[2]: _30 = _6
-29:33-29:34: @17[4]: _31 = _7
-29:29-29:34: @17[5]: _29 = Lt(move _30, move _31)"><span class="annotation">@17⦊</span>b &lt; c<span class="annotation">⦉@17</span></span></span><span class="code" style="--layer: 0">;</span></span>
-<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="30:9-30:17: @22[2]: FakeRead(ForLet, _32)"><span class="annotation">@22⦊</span>somebool<span class="annotation">⦉@22</span></span></span><span class="code" style="--layer: 0"> = </span><span><span class="code odd" style="--layer: 1" title="30:20-30:21: @18[6]: _34 = _6
-30:24-30:25: @18[8]: _35 = _5
-30:20-30:25: @18[9]: _33 = Lt(move _34, move _35)"><span class="annotation">@18⦊</span>b &lt; a<span class="annotation">⦉@18</span></span></span><span class="code" style="--layer: 0"> &amp;&amp; </span><span><span class="code even" style="--layer: 1" title="30:29-30:30: @21[2]: _37 = _6
-30:33-30:34: @21[4]: _38 = _7
-30:29-30:34: @21[5]: _36 = Lt(move _37, move _38)"><span class="annotation">@21⦊</span>b &lt; c<span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code odd" style="--layer: 1" title="29:9-29:17: @15[2]: FakeRead(ForLet, _25)"><span class="annotation">@15⦊</span>somebool<span class="annotation">⦉@15</span></span></span><span class="code" style="--layer: 0"> = </span><span><span class="code even" style="--layer: 1" title="29:20-29:21: @12[6]: _27 = _5
+29:24-29:25: @12[8]: _28 = _6
+29:20-29:25: @12[9]: _26 = Lt(move _27, move _28)"><span class="annotation">@12⦊</span>a &lt; b<span class="annotation">⦉@12</span></span></span><span class="code" style="--layer: 0"> &amp;&amp; </span><span><span class="code odd" style="--layer: 1" title="29:29-29:30: @14[2]: _30 = _6
+29:33-29:34: @14[4]: _31 = _7
+29:29-29:34: @14[5]: _29 = Lt(move _30, move _31)"><span class="annotation">@14⦊</span>b &lt; c<span class="annotation">⦉@14</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">    let </span><span><span class="code even" style="--layer: 1" title="30:9-30:17: @18[2]: FakeRead(ForLet, _32)"><span class="annotation">@18⦊</span>somebool<span class="annotation">⦉@18</span></span></span><span class="code" style="--layer: 0"> = </span><span><span class="code odd" style="--layer: 1" title="30:20-30:21: @15[6]: _34 = _6
+30:24-30:25: @15[8]: _35 = _5
+30:20-30:25: @15[9]: _33 = Lt(move _34, move _35)"><span class="annotation">@15⦊</span>b &lt; a<span class="annotation">⦉@15</span></span></span><span class="code" style="--layer: 0"> &amp;&amp; </span><span><span class="code even" style="--layer: 1" title="30:29-30:30: @17[2]: _37 = _6
+30:33-30:34: @17[4]: _38 = _7
+30:29-30:34: @17[5]: _36 = Lt(move _37, move _38)"><span class="annotation">@17⦊</span>b &lt; c<span class="annotation">⦉@17</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    if</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="34:9-34:16: @22[6]: _41 = _1
-33:9-34:16: @22[7]: _40 = Not(move _41)"><span class="annotation">@22⦊</span>!</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="34:9-34:16: @22[6]: _41 = _1
-33:9-34:16: @22[7]: _40 = Not(move _41)">        is_true<span class="annotation">⦉@22</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="36:9-36:14: @23[0]: _5 = const 2_i32
-35:5-38:6: @23[1]: _39 = const ()"><span class="annotation">@23⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="36:9-36:14: @23[0]: _5 = const 2_i32
-35:5-38:6: @23[1]: _39 = const ()">        a = 2</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="36:9-36:14: @23[0]: _5 = const 2_i32
-35:5-38:6: @23[1]: _39 = const ()">        ;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="36:9-36:14: @23[0]: _5 = const 2_i32
-35:5-38:6: @23[1]: _39 = const ()">    }<span class="annotation">⦉@23</span></span></span><span><span class="code odd" style="--layer: 1" title="38:6-38:6: @24[0]: _39 = const ()"><span class="annotation">@24⦊</span>‸<span class="annotation">⦉@24</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="34:9-34:16: @18[6]: _41 = _1
+33:9-34:16: @18[7]: _40 = Not(move _41)"><span class="annotation">@18⦊</span>!</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="34:9-34:16: @18[6]: _41 = _1
+33:9-34:16: @18[7]: _40 = Not(move _41)">        is_true<span class="annotation">⦉@18</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="36:9-36:14: @19[0]: _5 = const 2_i32
+35:5-38:6: @19[1]: _39 = const ()"><span class="annotation">@19⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="36:9-36:14: @19[0]: _5 = const 2_i32
+35:5-38:6: @19[1]: _39 = const ()">        a = 2</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="36:9-36:14: @19[0]: _5 = const 2_i32
+35:5-38:6: @19[1]: _39 = const ()">        ;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="36:9-36:14: @19[0]: _5 = const 2_i32
+35:5-38:6: @19[1]: _39 = const ()">    }<span class="annotation">⦉@19</span></span></span><span><span class="code odd" style="--layer: 1" title="38:6-38:6: @20[0]: _39 = const ()"><span class="annotation">@20⦊</span>‸<span class="annotation">⦉@20</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    if</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="41:9-41:16: @25[4]: _43 = _1"><span class="annotation">@25⦊</span>is_true<span class="annotation">⦉@25</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="43:9-43:15: @26[0]: _6 = const 30_i32
-42:5-45:6: @26[1]: _42 = const ()"><span class="annotation">@26⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="43:9-43:15: @26[0]: _6 = const 30_i32
-42:5-45:6: @26[1]: _42 = const ()">        b = 30</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="43:9-43:15: @26[0]: _6 = const 30_i32
-42:5-45:6: @26[1]: _42 = const ()">        ;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="43:9-43:15: @26[0]: _6 = const 30_i32
-42:5-45:6: @26[1]: _42 = const ()">    }<span class="annotation">⦉@26</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="41:9-41:16: @21[4]: _43 = _1"><span class="annotation">@21⦊</span>is_true<span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code odd" style="--layer: 1" title="43:9-43:15: @22[0]: _6 = const 30_i32
+42:5-45:6: @22[1]: _42 = const ()"><span class="annotation">@22⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="43:9-43:15: @22[0]: _6 = const 30_i32
+42:5-45:6: @22[1]: _42 = const ()">        b = 30</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="43:9-43:15: @22[0]: _6 = const 30_i32
+42:5-45:6: @22[1]: _42 = const ()">        ;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="43:9-43:15: @22[0]: _6 = const 30_i32
+42:5-45:6: @22[1]: _42 = const ()">    }<span class="annotation">⦉@22</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    else</span></span>
-<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="48:9-48:16: @27[0]: _7 = const 400_i32
-47:5-50:6: @27[1]: _42 = const ()"><span class="annotation">@27⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="48:9-48:16: @27[0]: _7 = const 400_i32
-47:5-50:6: @27[1]: _42 = const ()">        c = 400</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="48:9-48:16: @27[0]: _7 = const 400_i32
-47:5-50:6: @27[1]: _42 = const ()">        ;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="48:9-48:16: @27[0]: _7 = const 400_i32
-47:5-50:6: @27[1]: _42 = const ()">    }<span class="annotation">⦉@27</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="48:9-48:16: @23[0]: _7 = const 400_i32
+47:5-50:6: @23[1]: _42 = const ()"><span class="annotation">@23⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="48:9-48:16: @23[0]: _7 = const 400_i32
+47:5-50:6: @23[1]: _42 = const ()">        c = 400</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="48:9-48:16: @23[0]: _7 = const 400_i32
+47:5-50:6: @23[1]: _42 = const ()">        ;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="48:9-48:16: @23[0]: _7 = const 400_i32
+47:5-50:6: @23[1]: _42 = const ()">    }<span class="annotation">⦉@23</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code odd" style="--layer: 1" title="52:9-52:16: @28[5]: _46 = _1
-52:8-52:16: @28[6]: _45 = Not(move _46)"><span class="annotation">@28⦊</span>!is_true<span class="annotation">⦉@28</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="53:9-53:14: @29[0]: _5 = const 2_i32
-52:17-54:6: @29[1]: _44 = const ()"><span class="annotation">@29⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="53:9-53:14: @29[0]: _5 = const 2_i32
-52:17-54:6: @29[1]: _44 = const ()">        a = 2;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="53:9-53:14: @29[0]: _5 = const 2_i32
-52:17-54:6: @29[1]: _44 = const ()">    }<span class="annotation">⦉@29</span></span></span><span><span class="code odd" style="--layer: 1" title="54:6-54:6: @30[0]: _44 = const ()"><span class="annotation">@30⦊</span>‸<span class="annotation">⦉@30</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code odd" style="--layer: 1" title="52:9-52:16: @24[5]: _46 = _1
+52:8-52:16: @24[6]: _45 = Not(move _46)"><span class="annotation">@24⦊</span>!is_true<span class="annotation">⦉@24</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="53:9-53:14: @25[0]: _5 = const 2_i32
+52:17-54:6: @25[1]: _44 = const ()"><span class="annotation">@25⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="53:9-53:14: @25[0]: _5 = const 2_i32
+52:17-54:6: @25[1]: _44 = const ()">        a = 2;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="53:9-53:14: @25[0]: _5 = const 2_i32
+52:17-54:6: @25[1]: _44 = const ()">    }<span class="annotation">⦉@25</span></span></span><span><span class="code odd" style="--layer: 1" title="54:6-54:6: @26[0]: _44 = const ()"><span class="annotation">@26⦊</span>‸<span class="annotation">⦉@26</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="56:8-56:15: @31[3]: _47 = _1"><span class="annotation">@31⦊</span>is_true<span class="annotation">⦉@31</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="57:9-57:15: @32[0]: _6 = const 30_i32
-56:16-58:6: @32[1]: _0 = const ()"><span class="annotation">@32⦊</span>{</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="57:9-57:15: @32[0]: _6 = const 30_i32
-56:16-58:6: @32[1]: _0 = const ()">        b = 30;</span></span>
-<span class="line"><span class="code odd" style="--layer: 1" title="57:9-57:15: @32[0]: _6 = const 30_i32
-56:16-58:6: @32[1]: _0 = const ()">    }<span class="annotation">⦉@32</span></span></span><span class="code" style="--layer: 0"> else </span><span><span class="code even" style="--layer: 1" title="59:9-59:16: @33[0]: _7 = const 400_i32
-58:12-60:6: @33[1]: _0 = const ()"><span class="annotation">@33⦊</span>{</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="59:9-59:16: @33[0]: _7 = const 400_i32
-58:12-60:6: @33[1]: _0 = const ()">        c = 400;</span></span>
-<span class="line"><span class="code even" style="--layer: 1" title="59:9-59:16: @33[0]: _7 = const 400_i32
-58:12-60:6: @33[1]: _0 = const ()">    }<span class="annotation">⦉@33</span></span></span><span class="code" style="--layer: 0"></span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="61:2-61:2: @34.Return: return"><span class="annotation">@34⦊</span>‸<span class="annotation">⦉@34</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="56:8-56:15: @27[3]: _47 = _1"><span class="annotation">@27⦊</span>is_true<span class="annotation">⦉@27</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="57:9-57:15: @28[0]: _6 = const 30_i32
+56:16-58:6: @28[1]: _0 = const ()"><span class="annotation">@28⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="57:9-57:15: @28[0]: _6 = const 30_i32
+56:16-58:6: @28[1]: _0 = const ()">        b = 30;</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="57:9-57:15: @28[0]: _6 = const 30_i32
+56:16-58:6: @28[1]: _0 = const ()">    }<span class="annotation">⦉@28</span></span></span><span class="code" style="--layer: 0"> else </span><span><span class="code even" style="--layer: 1" title="59:9-59:16: @29[0]: _7 = const 400_i32
+58:12-60:6: @29[1]: _0 = const ()"><span class="annotation">@29⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="59:9-59:16: @29[0]: _7 = const 400_i32
+58:12-60:6: @29[1]: _0 = const ()">        c = 400;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="59:9-59:16: @29[0]: _7 = const 400_i32
+58:12-60:6: @29[1]: _0 = const ()">    }<span class="annotation">⦉@29</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="61:2-61:2: @30.Return: return"><span class="annotation">@30⦊</span>‸<span class="annotation">⦉@30</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-eq.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-eq.-------.InstrumentCoverage.0.html
index 2e128181c5e..9858b270d7e 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-eq.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-eq.-------.InstrumentCoverage.0.html
@@ -69,6 +69,6 @@ For revisions in Pull Requests (PR):
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 3"><span class="line">                       <span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>‸<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">PartialEq</span><span><span class="code odd" style="--layer: 1" title="4:33-4:33: @4.Return: return"><span class="annotation">@4⦊</span>‸<span class="annotation">⦉@4</span></span></span></span></div>
+<div class="code" style="counter-reset: line 3"><span class="line">                       <span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>‸<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">PartialEq</span><span><span class="code odd" style="--layer: 1" title="4:33-4:33: @3.Return: return"><span class="annotation">@3⦊</span>‸<span class="annotation">⦉@3</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-ne.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-ne.-------.InstrumentCoverage.0.html
index 637b1c62086..bf94e5cbf73 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-ne.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-ne.-------.InstrumentCoverage.0.html
@@ -69,6 +69,6 @@ For revisions in Pull Requests (PR):
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 3"><span class="line">                       <span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>‸<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">PartialEq</span><span><span class="code odd" style="--layer: 1" title="4:33-4:33: @4.Return: return"><span class="annotation">@4⦊</span>‸<span class="annotation">⦉@4</span></span></span></span></div>
+<div class="code" style="counter-reset: line 3"><span class="line">                       <span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>‸<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">PartialEq</span><span><span class="code odd" style="--layer: 1" title="4:33-4:33: @3.Return: return"><span class="annotation">@3⦊</span>‸<span class="annotation">⦉@3</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.unused/unused.foo.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.unused/unused.foo.-------.InstrumentCoverage.0.html
index 45fec46f55c..ef431a356c2 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.unused/unused.foo.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.unused/unused.foo.-------.InstrumentCoverage.0.html
@@ -77,11 +77,11 @@ For revisions in Pull Requests (PR):
 3:11-3:17: @2[3]: _4 = Lt(move _5, const 10_i32)
 3:11-3:17: @2[5]: FakeRead(ForMatchedPlace, _4)"><span class="annotation">@1,2⦊</span>i &lt; 10<span class="annotation">⦉@1,2</span></span></span><span class="code" style="--layer: 0"> {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="4:9-4:10: @5[3]: _8 = _2
-4:9-4:15: @5[4]: _7 = Ne(move _8, const 0_i32)"><span class="annotation">@3,5⦊</span>i != 0<span class="annotation">⦉@3,5</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="4:19-4:20: @8[2]: _10 = _2
-4:19-4:25: @8[3]: _9 = Ne(move _10, const 0_i32)"><span class="annotation">@8⦊</span>i != 0<span class="annotation">⦉@8</span></span></span><span class="code" style="--layer: 0">;</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="5:9-5:15: @9[3]: _11 = CheckedAdd(_2, const 1_i32)
-5:9-5:15: @10[0]: _2 = move (_11.0: i32)"><span class="annotation">@9,10⦊</span>i += 1<span class="annotation">⦉@9,10</span></span></span><span class="code" style="--layer: 0">;</span></span>
+4:9-4:15: @5[4]: _7 = Ne(move _8, const 0_i32)"><span class="annotation">@3,5⦊</span>i != 0<span class="annotation">⦉@3,5</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="4:19-4:20: @7[2]: _10 = _2
+4:19-4:25: @7[3]: _9 = Ne(move _10, const 0_i32)"><span class="annotation">@7⦊</span>i != 0<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="5:9-5:15: @8[3]: _11 = CheckedAdd(_2, const 1_i32)
+5:9-5:15: @9[0]: _2 = move (_11.0: i32)"><span class="annotation">@8,9⦊</span>i += 1<span class="annotation">⦉@8,9</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="7:2-7:2: @11.Return: return"><span class="annotation">@4,11⦊</span>‸<span class="annotation">⦉@4,11</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="7:2-7:2: @10.Return: return"><span class="annotation">@4,10⦊</span>‸<span class="annotation">⦉@4,10</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.unused/unused.unused_template_func.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.unused/unused.unused_template_func.-------.InstrumentCoverage.0.html
index 9b32bcb47f6..be4f5efc5db 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.unused/unused.unused_template_func.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.unused/unused.unused_template_func.-------.InstrumentCoverage.0.html
@@ -77,11 +77,11 @@ For revisions in Pull Requests (PR):
 11:11-11:17: @2[3]: _4 = Lt(move _5, const 10_i32)
 11:11-11:17: @2[5]: FakeRead(ForMatchedPlace, _4)"><span class="annotation">@1,2⦊</span>i &lt; 10<span class="annotation">⦉@1,2</span></span></span><span class="code" style="--layer: 0"> {</span></span>
 <span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="12:9-12:10: @5[3]: _8 = _2
-12:9-12:15: @5[4]: _7 = Ne(move _8, const 0_i32)"><span class="annotation">@3,5⦊</span>i != 0<span class="annotation">⦉@3,5</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="12:19-12:20: @8[2]: _10 = _2
-12:19-12:25: @8[3]: _9 = Ne(move _10, const 0_i32)"><span class="annotation">@8⦊</span>i != 0<span class="annotation">⦉@8</span></span></span><span class="code" style="--layer: 0">;</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="13:9-13:15: @9[3]: _11 = CheckedAdd(_2, const 1_i32)
-13:9-13:15: @10[0]: _2 = move (_11.0: i32)"><span class="annotation">@9,10⦊</span>i += 1<span class="annotation">⦉@9,10</span></span></span><span class="code" style="--layer: 0">;</span></span>
+12:9-12:15: @5[4]: _7 = Ne(move _8, const 0_i32)"><span class="annotation">@3,5⦊</span>i != 0<span class="annotation">⦉@3,5</span></span></span><span class="code" style="--layer: 0"> || </span><span><span class="code odd" style="--layer: 1" title="12:19-12:20: @7[2]: _10 = _2
+12:19-12:25: @7[3]: _9 = Ne(move _10, const 0_i32)"><span class="annotation">@7⦊</span>i != 0<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0">;</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="13:9-13:15: @8[3]: _11 = CheckedAdd(_2, const 1_i32)
+13:9-13:15: @9[0]: _2 = move (_11.0: i32)"><span class="annotation">@8,9⦊</span>i += 1<span class="annotation">⦉@8,9</span></span></span><span class="code" style="--layer: 0">;</span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="15:2-15:2: @11.Return: return"><span class="annotation">@4,11⦊</span>‸<span class="annotation">⦉@4,11</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="15:2-15:2: @10.Return: return"><span class="annotation">@4,10⦊</span>‸<span class="annotation">⦉@4,10</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage/lib/used_inline_crate.rs b/src/test/run-make-fulldeps/coverage/lib/used_inline_crate.rs
index f4c3dd46f76..4a052756d4e 100644
--- a/src/test/run-make-fulldeps/coverage/lib/used_inline_crate.rs
+++ b/src/test/run-make-fulldeps/coverage/lib/used_inline_crate.rs
@@ -28,12 +28,12 @@ pub fn used_inline_function() {
     }
     use_this_lib_crate();
 }
-// Expect for above function:
-//
-// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
-//
-// With `#[inline(always)]` this function is instantiated twice, in both the library crate (which
-// does not use it) and the `uses_inline_crate` binary (which does use/call it).
+
+
+
+
+
+
 
 #[inline(always)]
 pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
diff --git a/src/test/run-make-fulldeps/issue-83045/Makefile b/src/test/run-make-fulldeps/issue-83045/Makefile
new file mode 100644
index 00000000000..34853cb1d31
--- /dev/null
+++ b/src/test/run-make-fulldeps/issue-83045/Makefile
@@ -0,0 +1,33 @@
+include ../../run-make-fulldeps/tools.mk
+
+# This test case creates a situation where the crate loader would run
+# into an ICE when confronted with an invalid setup where it cannot
+# find the dependency of a direct dependency.
+#
+# The test case makes sure that the compiler produces the expected
+# error message but does not ICE immediately after.
+#
+# See https://github.com/rust-lang/rust/issues/83045
+
+# This is a platform-independent issue, no need to waste time testing
+# everywhere.
+# only-x86_64
+# only-linux
+
+# NOTE: We use BARE_RUSTC below so that the compiler can't find liba.rlib
+#       If we used RUSTC the additional '-L TMPDIR' option would allow rustc to
+#       actually find the crate.
+#
+#       We check that we get the expected error message
+#       But that we do not get an ICE
+
+all:
+	$(RUSTC) --crate-name=a --crate-type=rlib a.rs --verbose
+	$(RUSTC) --crate-name=b --crate-type=rlib --extern a=$(TMPDIR)/liba.rlib b.rs --verbose
+	$(BARE_RUSTC) --out-dir $(TMPDIR) \
+	              --extern b=$(TMPDIR)/libb.rlib \
+				  --crate-type=rlib \
+				  --edition=2018 \
+				  c.rs 2>&1 | tee $(TMPDIR)/output.txt || exit 0
+	$(CGREP) E0463 < $(TMPDIR)/output.txt
+	$(CGREP) -v "internal compiler error" < $(TMPDIR)/output.txt
diff --git a/src/test/run-make-fulldeps/issue-83045/a.rs b/src/test/run-make-fulldeps/issue-83045/a.rs
new file mode 100644
index 00000000000..66d9f758e9d
--- /dev/null
+++ b/src/test/run-make-fulldeps/issue-83045/a.rs
@@ -0,0 +1 @@
+// empty on purpose
diff --git a/src/test/run-make-fulldeps/issue-83045/b.rs b/src/test/run-make-fulldeps/issue-83045/b.rs
new file mode 100644
index 00000000000..f4876cfa457
--- /dev/null
+++ b/src/test/run-make-fulldeps/issue-83045/b.rs
@@ -0,0 +1 @@
+extern crate a;
diff --git a/src/test/run-make-fulldeps/issue-83045/c.rs b/src/test/run-make-fulldeps/issue-83045/c.rs
new file mode 100644
index 00000000000..e0c4525499e
--- /dev/null
+++ b/src/test/run-make-fulldeps/issue-83045/c.rs
@@ -0,0 +1 @@
+use b as _;
diff --git a/src/test/run-make/incr-prev-body-beyond-eof/Makefile b/src/test/run-make/incr-prev-body-beyond-eof/Makefile
index 49a7ee5f900..24eea3acaea 100644
--- a/src/test/run-make/incr-prev-body-beyond-eof/Makefile
+++ b/src/test/run-make/incr-prev-body-beyond-eof/Makefile
@@ -1,7 +1,7 @@
-include ../../run-make-fulldeps/tools.mk
+# ignore-none no-std is not supported
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std`
 
-# FIXME https://github.com/rust-lang/rust/issues/78911
-# ignore-32bit wrong/no cross compiler and sometimes we pass wrong gcc args (-m64)
+include ../../run-make-fulldeps/tools.mk
 
 # Tests that we don't ICE during incremental compilation after modifying a
 # function span such that its previous end line exceeds the number of lines
@@ -14,6 +14,6 @@ all:
 	mkdir $(SRC)
 	mkdir $(INCR)
 	cp a.rs $(SRC)/main.rs
-	$(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs
+	$(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET)
 	cp b.rs $(SRC)/main.rs
-	$(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs
+	$(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET)
diff --git a/src/test/run-make/issue-36710/Makefile b/src/test/run-make/issue-36710/Makefile
index b0e8451ff5d..b5270ad2ba9 100644
--- a/src/test/run-make/issue-36710/Makefile
+++ b/src/test/run-make/issue-36710/Makefile
@@ -1,13 +1,20 @@
-include ../../run-make-fulldeps/tools.mk
+# ignore-riscv64 $(call RUN,foo) expects to run the target executable natively
+#                              so it won't work with remote-test-server
+# ignore-arm Another build using remote-test-server
+# ignore-none no-std is not supported
+# ignore-wasm32 FIXME: don't attempt to compile C++ to WASM
+# ignore-wasm64 FIXME: don't attempt to compile C++ to WASM
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std`
+# ignore-musl FIXME: this makefile needs teaching how to use a musl toolchain
+#                    (see dist-i586-gnu-i586-i686-musl Dockerfile)
 
-# FIXME https://github.com/rust-lang/rust/issues/78911
-# ignore-32bit wrong/no cross compiler and sometimes we pass wrong gcc args (-m64)
+include ../../run-make-fulldeps/tools.mk
 
 all: foo
 	$(call RUN,foo)
 
 foo: foo.rs $(call NATIVE_STATICLIB,foo)
-	$(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS)
+	$(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) --target $(TARGET)
 
 $(TMPDIR)/libfoo.o: foo.cpp
 	$(call COMPILE_OBJ_CXX,$@,$<)
diff --git a/src/test/run-make/issue-83112-incr-test-moved-file/Makefile b/src/test/run-make/issue-83112-incr-test-moved-file/Makefile
index 76ecaba0f6a..2f796e5b2fc 100644
--- a/src/test/run-make/issue-83112-incr-test-moved-file/Makefile
+++ b/src/test/run-make/issue-83112-incr-test-moved-file/Makefile
@@ -1,7 +1,7 @@
 include ../../run-make-fulldeps/tools.mk
 
-# FIXME https://github.com/rust-lang/rust/issues/78911
-# ignore-32bit wrong/no cross compiler and sometimes we pass wrong gcc args (-m64)
+# ignore-none no-std is not supported
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for 'std'
 
 # Regression test for issue #83112
 # The generated test harness code contains spans with a dummy location,
@@ -20,6 +20,6 @@ all:
 	mkdir $(SRC)/mydir
 	mkdir $(INCR)
 	cp main.rs $(SRC)/main.rs
-	$(RUSTC) --test -C incremental=$(INCR) $(SRC)/main.rs
+	$(RUSTC) --test -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET)
 	mv $(SRC)/main.rs $(SRC)/mydir/main.rs
-	$(RUSTC) --test -C incremental=$(INCR) $(SRC)/mydir/main.rs
+	$(RUSTC) --test -C incremental=$(INCR) $(SRC)/mydir/main.rs --target $(TARGET)
diff --git a/src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml b/src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml
new file mode 100644
index 00000000000..a4df102d245
--- /dev/null
+++ b/src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml
@@ -0,0 +1,21 @@
+goto: file://|DOC_PATH|/index.html
+write: (".search-input", "Foo")
+// Waiting for the search results to appear...
+wait-for: "#titles"
+assert: ("#titles > button:nth-of-type(1)", "class", "selected")
+
+// To go back to the original "state"
+goto: file://|DOC_PATH|/index.html
+write: (".search-input", "-> String")
+// Waiting for the search results to appear...
+wait-for: "#titles"
+// With this search, only the last tab shouldn't be empty so it should be selected.
+assert: ("#titles > button:nth-of-type(3)", "class", "selected")
+
+// To go back to the original "state"
+goto: file://|DOC_PATH|/index.html
+write: (".search-input", "-> Something")
+// Waiting for the search results to appear...
+wait-for: "#titles"
+// With this search, all the tabs are empty so the first one should remain selected.
+assert: ("#titles > button:nth-of-type(1)", "class", "selected")
diff --git a/src/test/rustdoc-json/reexport/in_root_and_mod.rs b/src/test/rustdoc-json/reexport/in_root_and_mod.rs
new file mode 100644
index 00000000000..e3cecbdd7ff
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/in_root_and_mod.rs
@@ -0,0 +1,15 @@
+#![feature(no_core)]
+#![no_core]
+
+mod foo {
+    // @set foo_id = in_root_and_mod.json "$.index[*][?(@.name=='Foo')].id"
+    pub struct Foo;
+}
+
+// @has - "$.index[*][?(@.name=='in_root_and_mod')].inner.items[*]" $foo_id
+pub use foo::Foo;
+
+pub mod bar {
+    // @has - "$.index[*][?(@.name=='bar')].inner.items[*]" $foo_id
+    pub use crate::foo::Foo;
+}
diff --git a/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs
new file mode 100644
index 00000000000..2daadf7620c
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs
@@ -0,0 +1,20 @@
+#![feature(no_core)]
+#![no_core]
+
+pub mod foo {
+    // @set bar_id = in_root_and_mod_pub.json "$.index[*][?(@.name=='Bar')].id"
+    // @has - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id
+    pub struct Bar;
+}
+
+// @set root_import_id = - "$.index[*][?(@.inner.source=='foo::Bar')].id"
+// @is - "$.index[*][?(@.inner.source=='foo::Bar')].inner.id" $bar_id
+// @has - "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.items[*]" $root_import_id
+pub use foo::Bar;
+
+pub mod baz {
+    // @set baz_import_id = - "$.index[*][?(@.inner.source=='crate::foo::Bar')].id"
+    // @is - "$.index[*][?(@.inner.source=='crate::foo::Bar')].inner.id" $bar_id
+    // @has - "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id
+    pub use crate::foo::Bar;
+}
diff --git a/src/test/rustdoc-json/reexport/rename_private.rs b/src/test/rustdoc-json/reexport/rename_private.rs
new file mode 100644
index 00000000000..fb8296f2337
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/rename_private.rs
@@ -0,0 +1,14 @@
+// edition:2018
+
+#![no_core]
+#![feature(no_core)]
+// @!has rename_private.json "$.index[*][?(@.name=='inner')]"
+mod inner {
+    // @!has - "$.index[*][?(@.name=='Public')]"
+    pub struct Public;
+}
+
+// @set newname_id = - "$.index[*][?(@.name=='NewName')].id"
+// @is - "$.index[*][?(@.name=='NewName')].kind" \"struct\"
+// @has - "$.index[*][?(@.name=='rename_private')].inner.items[*]" $newname_id
+pub use inner::Public as NewName;
diff --git a/src/test/rustdoc-ui/check-doc-alias-attr.stderr b/src/test/rustdoc-ui/check-doc-alias-attr.stderr
index f99d69dc101..250568be333 100644
--- a/src/test/rustdoc-ui/check-doc-alias-attr.stderr
+++ b/src/test/rustdoc-ui/check-doc-alias-attr.stderr
@@ -10,7 +10,7 @@ error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of s
 LL | #[doc(alias = 0)]
    |       ^^^^^^^^^
 
-error: '\"' character isn't allowed in `#[doc(alias = "...")]`
+error: '"' character isn't allowed in `#[doc(alias = "...")]`
   --> $DIR/check-doc-alias-attr.rs:9:15
    |
 LL | #[doc(alias = "\"")]
@@ -60,7 +60,7 @@ error: `#[doc(alias("a"))]` expects string literals
 LL | #[doc(alias(0))]
    |             ^
 
-error: '\"' character isn't allowed in `#[doc(alias("..."))]`
+error: '"' character isn't allowed in `#[doc(alias("..."))]`
   --> $DIR/check-doc-alias-attr.rs:20:13
    |
 LL | #[doc(alias("\""))]
diff --git a/src/test/rustdoc-ui/doc-spotlight.fixed b/src/test/rustdoc-ui/doc-spotlight.fixed
new file mode 100644
index 00000000000..6c90aace689
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-spotlight.fixed
@@ -0,0 +1,10 @@
+// ignore-tidy-linelength
+// check-pass
+// run-rustfix
+
+#![feature(doc_notable_trait)]
+
+#[doc(notable_trait)]
+//~^ WARN unknown `doc` attribute `spotlight`
+//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+trait MyTrait {}
diff --git a/src/test/rustdoc-ui/doc-spotlight.rs b/src/test/rustdoc-ui/doc-spotlight.rs
new file mode 100644
index 00000000000..7cea553c4b0
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-spotlight.rs
@@ -0,0 +1,10 @@
+// ignore-tidy-linelength
+// check-pass
+// run-rustfix
+
+#![feature(doc_notable_trait)]
+
+#[doc(spotlight)]
+//~^ WARN unknown `doc` attribute `spotlight`
+//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+trait MyTrait {}
diff --git a/src/test/rustdoc-ui/doc-spotlight.stderr b/src/test/rustdoc-ui/doc-spotlight.stderr
new file mode 100644
index 00000000000..e79cdc3d77a
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-spotlight.stderr
@@ -0,0 +1,14 @@
+warning: unknown `doc` attribute `spotlight`
+  --> $DIR/doc-spotlight.rs:7:7
+   |
+LL | #[doc(spotlight)]
+   |       ^^^^^^^^^ help: use `notable_trait` instead
+   |
+   = note: `#[warn(invalid_doc_attributes)]` on by default
+   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: `doc(spotlight)` was renamed to `doc(notable_trait)`
+   = note: `doc(spotlight)` is now a no-op
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
new file mode 100644
index 00000000000..925fc515a3e
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
@@ -0,0 +1,13 @@
+#![deny(warnings)]
+
+//! Linking to [foo@banana] and [`bar@banana!()`].
+//~^ ERROR unknown disambiguator `foo`
+//~| ERROR unknown disambiguator `bar`
+//! And to [no disambiguator](@nectarine) and [another](@apricot!()).
+//~^ ERROR unknown disambiguator ``
+//~| ERROR unknown disambiguator ``
+//! And with weird backticks: [``foo@hello``] [foo`@`hello].
+//~^ ERROR unknown disambiguator `foo`
+//~| ERROR unknown disambiguator `foo`
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
new file mode 100644
index 00000000000..195aaca32a2
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
@@ -0,0 +1,45 @@
+error: unknown disambiguator `foo`
+  --> $DIR/unknown-disambiguator.rs:3:17
+   |
+LL | //! Linking to [foo@banana] and [`bar@banana!()`].
+   |                 ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unknown-disambiguator.rs:1:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
+
+error: unknown disambiguator `bar`
+  --> $DIR/unknown-disambiguator.rs:3:35
+   |
+LL | //! Linking to [foo@banana] and [`bar@banana!()`].
+   |                                   ^^^
+
+error: unknown disambiguator `foo`
+  --> $DIR/unknown-disambiguator.rs:9:34
+   |
+LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
+   |                                  ^^^
+
+error: unknown disambiguator `foo`
+  --> $DIR/unknown-disambiguator.rs:9:48
+   |
+LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
+   |                                                ^^^
+
+error: unknown disambiguator ``
+  --> $DIR/unknown-disambiguator.rs:6:31
+   |
+LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
+   |                               ^
+
+error: unknown disambiguator ``
+  --> $DIR/unknown-disambiguator.rs:6:57
+   |
+LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
+   |                                                         ^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/rustdoc/doc-spotlight.rs b/src/test/rustdoc/doc-notable_trait.rs
index ddd46c3c215..58a24b855d6 100644
--- a/src/test/rustdoc/doc-spotlight.rs
+++ b/src/test/rustdoc/doc-notable_trait.rs
@@ -1,4 +1,4 @@
-#![feature(doc_spotlight)]
+#![feature(doc_notable_trait)]
 
 pub struct Wrapper<T> {
     inner: T,
@@ -6,9 +6,9 @@ pub struct Wrapper<T> {
 
 impl<T: SomeTrait> SomeTrait for Wrapper<T> {}
 
-#[doc(spotlight)]
+#[doc(notable_trait)]
 pub trait SomeTrait {
-    // @has doc_spotlight/trait.SomeTrait.html
+    // @has doc_notable_trait/trait.SomeTrait.html
     // @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
     fn wrap_me(self) -> Wrapper<Self> where Self: Sized {
         Wrapper {
@@ -21,7 +21,7 @@ pub struct SomeStruct;
 impl SomeTrait for SomeStruct {}
 
 impl SomeStruct {
-    // @has doc_spotlight/struct.SomeStruct.html
+    // @has doc_notable_trait/struct.SomeStruct.html
     // @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
     // @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
     pub fn new() -> SomeStruct {
@@ -29,7 +29,7 @@ impl SomeStruct {
     }
 }
 
-// @has doc_spotlight/fn.bare_fn.html
+// @has doc_notable_trait/fn.bare_fn.html
 // @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
 pub fn bare_fn() -> SomeStruct {
     SomeStruct
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
index 8b1a3887f15..51cea4f6ba9 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
@@ -33,7 +33,7 @@ macro_rules! fake_lint_pass {
                     if !cx.sess().contains_name(attrs, $attr) {
                         cx.lint(CRATE_NOT_OKAY, |lint| {
                              let msg = format!("crate is not marked with #![{}]", $attr);
-                             lint.build(&msg).set_span(krate.item.span).emit()
+                             lint.build(&msg).set_span(krate.item.inner).emit()
                         });
                     }
                 )*
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
index c9269d2b9ba..ef5353e6d8c 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
@@ -31,7 +31,7 @@ impl<'tcx> LateLintPass<'tcx> for Pass {
         if !cx.sess().contains_name(attrs, Symbol::intern("crate_okay")) {
             cx.lint(CRATE_NOT_OKAY, |lint| {
                 lint.build("crate is not marked with #![crate_okay]")
-                    .set_span(krate.item.span)
+                    .set_span(krate.item.inner)
                     .emit()
             });
         }
diff --git a/src/test/ui/asm/const.rs b/src/test/ui/asm/const.rs
index e08da24f44a..22bc790713d 100644
--- a/src/test/ui/asm/const.rs
+++ b/src/test/ui/asm/const.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // only-x86_64
 // run-pass
 
diff --git a/src/test/ui/asm/inline-syntax.arm.stderr b/src/test/ui/asm/inline-syntax.arm.stderr
index 78b85dfde33..56e6572fc67 100644
--- a/src/test/ui/asm/inline-syntax.arm.stderr
+++ b/src/test/ui/asm/inline-syntax.arm.stderr
@@ -1,14 +1,74 @@
-error: att syntax is the default syntax on this target, and trying to use this directive may cause issues
-  --> $DIR/inline-syntax.rs:23:15
+error: unknown directive
+  --> $DIR/inline-syntax.rs:22:15
+   |
+LL |         asm!(".intel_syntax noprefix", "nop");
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .intel_syntax noprefix
+   |     ^
+
+error: unknown directive
+  --> $DIR/inline-syntax.rs:25:15
+   |
+LL |         asm!(".intel_syntax aaa noprefix", "nop");
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .intel_syntax aaa noprefix
+   |     ^
+
+error: unknown directive
+  --> $DIR/inline-syntax.rs:28:15
    |
 LL |         asm!(".att_syntax noprefix", "nop");
-   |               ^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .att_syntax noprefix
+   |     ^
 
-error: att syntax is the default syntax on this target, and trying to use this directive may cause issues
-  --> $DIR/inline-syntax.rs:26:15
+error: unknown directive
+  --> $DIR/inline-syntax.rs:31:15
    |
 LL |         asm!(".att_syntax bbb noprefix", "nop");
-   |               ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .att_syntax bbb noprefix
+   |     ^
+
+error: unknown directive
+  --> $DIR/inline-syntax.rs:34:15
+   |
+LL |         asm!(".intel_syntax noprefix; nop");
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .intel_syntax noprefix; nop
+   |     ^
+
+error: unknown directive
+  --> $DIR/inline-syntax.rs:40:13
+   |
+LL |             .intel_syntax noprefix
+   |             ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:13
+   |
+LL |             .intel_syntax noprefix
+   |             ^
 
-error: aborting due to 2 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/asm/inline-syntax.rs b/src/test/ui/asm/inline-syntax.rs
index 9048282456e..78dde5a58e1 100644
--- a/src/test/ui/asm/inline-syntax.rs
+++ b/src/test/ui/asm/inline-syntax.rs
@@ -1,9 +1,12 @@
 // needs-llvm-components: arm
 // revisions: x86_64 arm
 //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[x86_64] check-pass
 //[arm] compile-flags: --target armv7-unknown-linux-gnueabihf
+//[arm] build-fail
 
 #![feature(no_core, lang_items, rustc_attrs)]
+#![crate_type = "rlib"]
 #![no_core]
 
 #[rustc_builtin_macro]
@@ -14,26 +17,30 @@ macro_rules! asm {
 #[lang = "sized"]
 trait Sized {}
 
-fn main() {
+pub fn main() {
     unsafe {
         asm!(".intel_syntax noprefix", "nop");
-        //[x86_64]~^ ERROR intel syntax is the default syntax on this target
+        //[x86_64]~^ WARN avoid using `.intel_syntax`
+        //[arm]~^^ ERROR unknown directive
         asm!(".intel_syntax aaa noprefix", "nop");
-        //[x86_64]~^ ERROR intel syntax is the default syntax on this target
+        //[x86_64]~^ WARN avoid using `.intel_syntax`
+        //[arm]~^^ ERROR unknown directive
         asm!(".att_syntax noprefix", "nop");
-        //[x86_64]~^ ERROR using the .att_syntax directive may cause issues
-        //[arm]~^^ att syntax is the default syntax on this target
+        //[x86_64]~^ WARN avoid using `.att_syntax`
+        //[arm]~^^ ERROR unknown directive
         asm!(".att_syntax bbb noprefix", "nop");
-        //[x86_64]~^ ERROR using the .att_syntax directive may cause issues
-        //[arm]~^^ att syntax is the default syntax on this target
+        //[x86_64]~^ WARN avoid using `.att_syntax`
+        //[arm]~^^ ERROR unknown directive
         asm!(".intel_syntax noprefix; nop");
-        //[x86_64]~^ ERROR intel syntax is the default syntax on this target
+        //[x86_64]~^ WARN avoid using `.intel_syntax`
+        //[arm]~^^ ERROR unknown directive
 
         asm!(
             r"
             .intel_syntax noprefix
             nop"
         );
-        //[x86_64]~^^^ ERROR intel syntax is the default syntax on this target
+        //[x86_64]~^^^ WARN avoid using `.intel_syntax`
+        //[arm]~^^^^ ERROR unknown directive
     }
 }
diff --git a/src/test/ui/asm/inline-syntax.x86_64.stderr b/src/test/ui/asm/inline-syntax.x86_64.stderr
index 826657c98e1..5c03d3a002c 100644
--- a/src/test/ui/asm/inline-syntax.x86_64.stderr
+++ b/src/test/ui/asm/inline-syntax.x86_64.stderr
@@ -1,50 +1,40 @@
-error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues
-  --> $DIR/inline-syntax.rs:19:15
+warning: avoid using `.intel_syntax`, Intel syntax is the default
+  --> $DIR/inline-syntax.rs:22:15
    |
 LL |         asm!(".intel_syntax noprefix", "nop");
-   |               ^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+   |               ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(bad_asm_style)]` on by default
 
-error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues
-  --> $DIR/inline-syntax.rs:21:15
+warning: avoid using `.intel_syntax`, Intel syntax is the default
+  --> $DIR/inline-syntax.rs:25:15
    |
 LL |         asm!(".intel_syntax aaa noprefix", "nop");
-   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: using the .att_syntax directive may cause issues, use the att_syntax option instead
-  --> $DIR/inline-syntax.rs:23:15
+warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
+  --> $DIR/inline-syntax.rs:28:15
    |
 LL |         asm!(".att_syntax noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^
-   |
-help: remove the assembler directive and replace it with options(att_syntax)
-   |
-LL |         asm!("", "nop", options(att_syntax));
-   |              --       ^^^^^^^^^^^^^^^^^^^^^
 
-error: using the .att_syntax directive may cause issues, use the att_syntax option instead
-  --> $DIR/inline-syntax.rs:26:15
+warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
+  --> $DIR/inline-syntax.rs:31:15
    |
 LL |         asm!(".att_syntax bbb noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: remove the assembler directive and replace it with options(att_syntax)
-   |
-LL |         asm!("", "nop", options(att_syntax));
-   |              --       ^^^^^^^^^^^^^^^^^^^^^
 
-error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues
-  --> $DIR/inline-syntax.rs:29:15
+warning: avoid using `.intel_syntax`, Intel syntax is the default
+  --> $DIR/inline-syntax.rs:34:15
    |
 LL |         asm!(".intel_syntax noprefix; nop");
-   |               ^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+   |               ^^^^^^^^^^^^^^^^^^^^^^
 
-error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues
-  --> $DIR/inline-syntax.rs:34:14
+warning: avoid using `.intel_syntax`, Intel syntax is the default
+  --> $DIR/inline-syntax.rs:40:13
    |
-LL |               .intel_syntax noprefix
-   |  ______________^
-LL | |             nop"
-   | |_ help: remove this assembler directive
+LL |             .intel_syntax noprefix
+   |             ^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+warning: 6 warnings emitted
 
diff --git a/src/test/ui/asm/srcloc.rs b/src/test/ui/asm/srcloc.rs
index 1477e3dd566..ed8cefc58b7 100644
--- a/src/test/ui/asm/srcloc.rs
+++ b/src/test/ui/asm/srcloc.rs
@@ -1,7 +1,7 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // only-x86_64
 // build-fail
-
+// compile-flags: -Ccodegen-units=1
 #![feature(asm)]
 
 // Checks that inline asm errors are mapped to the correct line in the source code.
diff --git a/src/test/ui/asm/sym.rs b/src/test/ui/asm/sym.rs
index 9931697e412..634ef010e6f 100644
--- a/src/test/ui/asm/sym.rs
+++ b/src/test/ui/asm/sym.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // only-x86_64
 // only-linux
 // run-pass
@@ -76,5 +76,5 @@ fn main() {
     std::thread::spawn(|| {
         assert_eq!(static_addr!(S1), &S1 as *const u32);
         assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
-    });
+    }).join().unwrap();
 }
diff --git a/src/test/ui/associated-type-bounds/hrtb.rs b/src/test/ui/associated-type-bounds/hrtb.rs
new file mode 100644
index 00000000000..7ab3836493b
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/hrtb.rs
@@ -0,0 +1,65 @@
+// check-pass
+
+#![feature(associated_type_bounds)]
+
+trait A<'a> {}
+trait B<'b> {}
+fn foo<T>()
+where
+    for<'a> T: A<'a> + 'a,
+{
+}
+trait C<'c>: for<'a> A<'a> + for<'b> B<'b> {
+    type As;
+}
+struct D<T>
+where
+    T: for<'c> C<'c, As: A<'c>>,
+{
+    t: std::marker::PhantomData<T>,
+}
+
+trait E<'e> {
+    type As;
+}
+trait F<'f>: for<'a> A<'a> + for<'e> E<'e> {}
+struct G<T>
+where
+    for<'f> T: F<'f, As: E<'f>> + 'f,
+{
+    t: std::marker::PhantomData<T>,
+}
+
+trait I<'a, 'b, 'c> {
+    type As;
+}
+trait H<'d, 'e>: for<'f> I<'d, 'f, 'e> + 'd {}
+fn foo2<T>()
+where
+    T: for<'g> H<'g, 'g, As: for<'h> H<'h, 'g> + 'g>,
+{
+}
+
+fn foo3<T>()
+where
+    T: for<'i> H<'i, 'i, As: for<'j> H<'j, 'i, As: for<'k> I<'i, 'k, 'j> + 'j> + 'i>,
+{
+}
+fn foo4<T>()
+where
+    T: for<'l, 'i> H<'l, 'i, As: for<'j> H<'j, 'i, As: for<'k> I<'l, 'k, 'j> + 'j> + 'i>,
+{
+}
+
+struct X<'x, 'y> {
+    x: std::marker::PhantomData<&'x ()>,
+    y: std::marker::PhantomData<&'y ()>,
+}
+
+fn foo5<T>()
+where
+    T: for<'l, 'i> H<'l, 'i, As: for<'j> H<'j, 'i, As: for<'k> H<'j, 'k, As = X<'j, 'k>> + 'j> + 'i>
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr
index b0e9e33a6c3..89e05b61fc9 100644
--- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr
+++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr
@@ -2,13 +2,13 @@ error[E0271]: type mismatch resolving `<impl Bar as Foo>::Item == i32`
   --> $DIR/impl-trait-return-missing-constraint.rs:25:13
    |
 LL | fn bar() -> impl Bar {
-   |             -------- the expected opaque type
+   |             -------- the found opaque type
 ...
 LL | fn baz() -> impl Bar<Item = i32> {
-   |             ^^^^^^^^^^^^^^^^^^^^ expected associated type, found `i32`
+   |             ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type
    |
-   = note: expected associated type `<impl Bar as Foo>::Item`
-                         found type `i32`
+   = note:         expected type `i32`
+           found associated type `<impl Bar as Foo>::Item`
 help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32`
    |
 LL | fn bar() -> impl Bar<Item = i32> {
diff --git a/src/test/ui/associated-types/issue-44153.stderr b/src/test/ui/associated-types/issue-44153.stderr
index 8ef71087958..cafc8ec52ca 100644
--- a/src/test/ui/associated-types/issue-44153.stderr
+++ b/src/test/ui/associated-types/issue-44153.stderr
@@ -5,7 +5,7 @@ LL |     fn visit() {}
    |     ---------- required by `Visit::visit`
 ...
 LL |     <() as Visit>::visit();
-   |     ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&()`
+   |     ^^^^^^^^^^^^^^^^^^^^ expected `&()`, found `()`
    |
    = note: required because of the requirements on the impl of `Visit` for `()`
 
diff --git a/src/test/ui/async-await/issues/issue-64964.rs b/src/test/ui/async-await/issues/issue-64964.rs
index 11f6cb6af9c..5313d1715c4 100644
--- a/src/test/ui/async-await/issues/issue-64964.rs
+++ b/src/test/ui/async-await/issues/issue-64964.rs
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -C incremental=tmp/issue-64964
 // edition:2018
 
 // Regression test for ICE related to `await`ing in a method + incr. comp. (#64964)
diff --git a/src/test/ui/async-await/pin-needed-to-poll.rs b/src/test/ui/async-await/pin-needed-to-poll.rs
new file mode 100644
index 00000000000..0d1fe684f60
--- /dev/null
+++ b/src/test/ui/async-await/pin-needed-to-poll.rs
@@ -0,0 +1,47 @@
+use std::{
+    future::Future,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+struct Sleep;
+
+impl Future for Sleep {
+    type Output = ();
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        Poll::Ready(())
+    }
+}
+
+impl Drop for Sleep {
+    fn drop(&mut self) {}
+}
+
+fn sleep() -> Sleep {
+    Sleep
+}
+
+
+struct MyFuture {
+    sleep: Sleep,
+}
+
+impl MyFuture {
+    fn new() -> Self {
+        Self {
+            sleep: sleep(),
+        }
+    }
+}
+
+impl Future for MyFuture {
+    type Output = ();
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        self.sleep.poll(cx)
+        //~^ ERROR no method named `poll` found for struct `Sleep` in the current scope
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/pin-needed-to-poll.stderr b/src/test/ui/async-await/pin-needed-to-poll.stderr
new file mode 100644
index 00000000000..0756a4d59c1
--- /dev/null
+++ b/src/test/ui/async-await/pin-needed-to-poll.stderr
@@ -0,0 +1,22 @@
+error[E0599]: no method named `poll` found for struct `Sleep` in the current scope
+  --> $DIR/pin-needed-to-poll.rs:42:20
+   |
+LL | struct Sleep;
+   | ------------- method `poll` not found for this
+...
+LL |         self.sleep.poll(cx)
+   |                    ^^^^ method not found in `Sleep`
+   | 
+  ::: $SRC_DIR/core/src/future/future.rs:LL:COL
+   |
+LL |     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
+   |        ---- the method is available for `Pin<&mut Sleep>` here
+   |
+help: consider wrapping the receiver expression with the appropriate type
+   |
+LL |         Pin::new(&mut self.sleep).poll(cx)
+   |         ^^^^^^^^^^^^^           ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/binding/issue-53114-safety-checks.rs b/src/test/ui/binding/issue-53114-safety-checks.rs
index 28adb7571a9..ca4f0efd239 100644
--- a/src/test/ui/binding/issue-53114-safety-checks.rs
+++ b/src/test/ui/binding/issue-53114-safety-checks.rs
@@ -20,13 +20,13 @@ fn let_wild_gets_unsafe_field() {
     let u1 = U { a: I(0) };
     let u2 = U { a: I(1) };
     let p = P { a: &2, b: &3 };
-    let _ = &p.b;  //~ WARN    E0133
+    let _ = &p.b;  //~ WARN    reference to packed field
     //~^  WARN will become a hard error
     let _ = u1.a;  // #53114: should eventually signal error as well
     let _ = &u2.a; //~ ERROR  [E0133]
 
     // variation on above with `_` in substructure
-    let (_,) = (&p.b,);  //~ WARN     E0133
+    let (_,) = (&p.b,);  //~ WARN     reference to packed field
     //~^  WARN will become a hard error
     let (_,) = (u1.a,);  //~ ERROR   [E0133]
     let (_,) = (&u2.a,); //~ ERROR   [E0133]
@@ -36,13 +36,13 @@ fn match_unsafe_field_to_wild() {
     let u1 = U { a: I(0) };
     let u2 = U { a: I(1) };
     let p = P { a: &2, b: &3 };
-    match &p.b  { _ => { } } //~ WARN     E0133
+    match &p.b  { _ => { } } //~ WARN     reference to packed field
     //~^  WARN will become a hard error
     match u1.a  { _ => { } } //~ ERROR   [E0133]
     match &u2.a { _ => { } } //~ ERROR   [E0133]
 
     // variation on above with `_` in substructure
-    match (&p.b,)  { (_,) => { } } //~ WARN     E0133
+    match (&p.b,)  { (_,) => { } } //~ WARN     reference to packed field
     //~^  WARN will become a hard error
     match (u1.a,)  { (_,) => { } } //~ ERROR   [E0133]
     match (&u2.a,) { (_,) => { } } //~ ERROR   [E0133]
diff --git a/src/test/ui/binding/issue-53114-safety-checks.stderr b/src/test/ui/binding/issue-53114-safety-checks.stderr
index d4b8dfbade5..9e7deea4524 100644
--- a/src/test/ui/binding/issue-53114-safety-checks.stderr
+++ b/src/test/ui/binding/issue-53114-safety-checks.stderr
@@ -1,13 +1,43 @@
-warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
+warning: reference to packed field is unaligned
   --> $DIR/issue-53114-safety-checks.rs:23:13
    |
 LL |     let _ = &p.b;
    |             ^^^^
    |
-   = note: `#[warn(safe_packed_borrows)]` on by default
+   = note: `#[warn(unaligned_references)]` on by default
    = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
-   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+
+warning: reference to packed field is unaligned
+  --> $DIR/issue-53114-safety-checks.rs:29:17
+   |
+LL |     let (_,) = (&p.b,);
+   |                 ^^^^
+   |
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+
+warning: reference to packed field is unaligned
+  --> $DIR/issue-53114-safety-checks.rs:39:11
+   |
+LL |     match &p.b  { _ => { } }
+   |           ^^^^
+   |
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+
+warning: reference to packed field is unaligned
+  --> $DIR/issue-53114-safety-checks.rs:45:12
+   |
+LL |     match (&p.b,)  { (_,) => { } }
+   |            ^^^^
+   |
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
   --> $DIR/issue-53114-safety-checks.rs:26:13
@@ -17,16 +47,6 @@ LL |     let _ = &u2.a;
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
-warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
-  --> $DIR/issue-53114-safety-checks.rs:29:17
-   |
-LL |     let (_,) = (&p.b,);
-   |                 ^^^^
-   |
-   = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
-   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
-
 error[E0133]: access to union field is unsafe and requires unsafe function or block
   --> $DIR/issue-53114-safety-checks.rs:31:17
    |
@@ -43,16 +63,6 @@ LL |     let (_,) = (&u2.a,);
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
-warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
-  --> $DIR/issue-53114-safety-checks.rs:39:11
-   |
-LL |     match &p.b  { _ => { } }
-   |           ^^^^
-   |
-   = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
-   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
-
 error[E0133]: access to union field is unsafe and requires unsafe function or block
   --> $DIR/issue-53114-safety-checks.rs:41:11
    |
@@ -69,16 +79,6 @@ LL |     match &u2.a { _ => { } }
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
-warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
-  --> $DIR/issue-53114-safety-checks.rs:45:12
-   |
-LL |     match (&p.b,)  { (_,) => { } }
-   |            ^^^^
-   |
-   = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
-   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
-
 error[E0133]: access to union field is unsafe and requires unsafe function or block
   --> $DIR/issue-53114-safety-checks.rs:47:12
    |
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs
index 6fce2951505..82ec60a2e79 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs
@@ -23,7 +23,7 @@ fn test_missing_unsafe_warning_on_repr_packed() {
 
     let c = || {
         println!("{}", foo.x);
-        //~^ WARNING: borrow of packed field is unsafe and requires unsafe function or block
+        //~^ WARNING: reference to packed field is unaligned
         //~| WARNING: this was previously accepted by the compiler but is being phased out
         let _z = foo.x;
     };
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr
index 440b2c54c0a..e8cc164be87 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr
@@ -7,16 +7,16 @@ LL | #![feature(capture_disjoint_fields)]
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
 
-warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
+warning: reference to packed field is unaligned
   --> $DIR/repr_packed.rs:25:24
    |
 LL |         println!("{}", foo.x);
    |                        ^^^^^
    |
-   = note: `#[warn(safe_packed_borrows)]` on by default
+   = note: `#[warn(unaligned_references)]` on by default
    = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
-   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
 
 warning: 2 warnings emitted
 
diff --git a/src/test/ui/command/command-setgroups.rs b/src/test/ui/command/command-setgroups.rs
index 2067314f740..aff67f91bba 100644
--- a/src/test/ui/command/command-setgroups.rs
+++ b/src/test/ui/command/command-setgroups.rs
@@ -1,6 +1,5 @@
 // run-pass
 // ignore-windows - this is a unix-specific test
-// ignore-cloudabi
 // ignore-emscripten
 // ignore-sgx
 // ignore-musl - returns dummy result for _SC_NGROUPS_MAX
diff --git a/src/test/ui/const-generics/defaults/complex-unord-param.rs b/src/test/ui/const-generics/defaults/complex-unord-param.rs
index 82b3627d22f..d24e403e017 100644
--- a/src/test/ui/const-generics/defaults/complex-unord-param.rs
+++ b/src/test/ui/const-generics/defaults/complex-unord-param.rs
@@ -6,16 +6,16 @@
 #![allow(dead_code)]
 
 struct NestedArrays<'a, const N: usize, A: 'a, const M: usize, T:'a =u32> {
-  //[min]~^ ERROR type parameters must be declared prior to const parameters
-  args: &'a [&'a [T; M]; N],
-  specifier: A,
+    //[min]~^ ERROR type parameters must be declared prior to const parameters
+    args: &'a [&'a [T; M]; N],
+    specifier: A,
 }
 
 fn main() {
-  let array = [1, 2, 3];
-  let nest = [&array];
-  let _ = NestedArrays {
-    args: &nest,
-    specifier: true,
-  };
+    let array = [1, 2, 3];
+    let nest = [&array];
+    let _ = NestedArrays {
+        args: &nest,
+        specifier: true,
+    };
 }
diff --git a/src/test/ui/const-generics/defaults/default-annotation.rs b/src/test/ui/const-generics/defaults/default-annotation.rs
index e6e8d732bee..3febb7cffbf 100644
--- a/src/test/ui/const-generics/defaults/default-annotation.rs
+++ b/src/test/ui/const-generics/defaults/default-annotation.rs
@@ -13,8 +13,8 @@ pub struct ConstDefaultUnstable<const N: usize = 3>;
 
 #[stable(feature = "const_default_unstable", since="none")]
 pub struct ConstDefaultStable<const N: usize = {
-  #[stable(feature = "const_default_unstable_val", since="none")]
-  3
+    #[stable(feature = "const_default_unstable_val", since="none")]
+    3
 }>;
 
 fn main() {}
diff --git a/src/test/ui/const-generics/defaults/mismatch.rs b/src/test/ui/const-generics/defaults/mismatch.rs
index bf578468bb6..d85b756f538 100644
--- a/src/test/ui/const-generics/defaults/mismatch.rs
+++ b/src/test/ui/const-generics/defaults/mismatch.rs
@@ -8,16 +8,16 @@ pub struct Example3<const N: usize=13, T=u32>(T);
 pub struct Example4<const N: usize=13, const M: usize=4>;
 
 fn main() {
-  let e: Example::<13> = ();
-  //~^ Error: mismatched types
-  let e: Example2::<u32, 13> = ();
-  //~^ Error: mismatched types
-  let e: Example3::<13, u32> = ();
-  //~^ Error: mismatched types
-  let e: Example3::<7> = ();
-  //~^ Error: mismatched types
-  // FIXME(const_generics_defaults): There should be a note for the error below, but it is
-  // missing.
-  let e: Example4::<7> = ();
-  //~^ Error: mismatched types
+    let e: Example::<13> = ();
+    //~^ Error: mismatched types
+    let e: Example2::<u32, 13> = ();
+    //~^ Error: mismatched types
+    let e: Example3::<13, u32> = ();
+    //~^ Error: mismatched types
+    let e: Example3::<7> = ();
+    //~^ Error: mismatched types
+    // FIXME(const_generics_defaults): There should be a note for the error below, but it is
+    // missing.
+    let e: Example4::<7> = ();
+    //~^ Error: mismatched types
 }
diff --git a/src/test/ui/const-generics/defaults/mismatch.stderr b/src/test/ui/const-generics/defaults/mismatch.stderr
index c66eb4cd645..ff72c71c40f 100644
--- a/src/test/ui/const-generics/defaults/mismatch.stderr
+++ b/src/test/ui/const-generics/defaults/mismatch.stderr
@@ -1,51 +1,51 @@
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:11:26
+  --> $DIR/mismatch.rs:11:28
    |
-LL |   let e: Example::<13> = ();
-   |          -------------   ^^ expected struct `Example`, found `()`
-   |          |
-   |          expected due to this
+LL |     let e: Example::<13> = ();
+   |            -------------   ^^ expected struct `Example`, found `()`
+   |            |
+   |            expected due to this
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:13:32
+  --> $DIR/mismatch.rs:13:34
    |
-LL |   let e: Example2::<u32, 13> = ();
-   |          -------------------   ^^ expected struct `Example2`, found `()`
-   |          |
-   |          expected due to this
+LL |     let e: Example2::<u32, 13> = ();
+   |            -------------------   ^^ expected struct `Example2`, found `()`
+   |            |
+   |            expected due to this
    |
    = note: expected struct `Example2`
            found unit type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:15:32
+  --> $DIR/mismatch.rs:15:34
    |
-LL |   let e: Example3::<13, u32> = ();
-   |          -------------------   ^^ expected struct `Example3`, found `()`
-   |          |
-   |          expected due to this
+LL |     let e: Example3::<13, u32> = ();
+   |            -------------------   ^^ expected struct `Example3`, found `()`
+   |            |
+   |            expected due to this
    |
    = note: expected struct `Example3`
            found unit type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:17:26
+  --> $DIR/mismatch.rs:17:28
    |
-LL |   let e: Example3::<7> = ();
-   |          -------------   ^^ expected struct `Example3`, found `()`
-   |          |
-   |          expected due to this
+LL |     let e: Example3::<7> = ();
+   |            -------------   ^^ expected struct `Example3`, found `()`
+   |            |
+   |            expected due to this
    |
    = note: expected struct `Example3<7_usize>`
            found unit type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:21:26
+  --> $DIR/mismatch.rs:21:28
    |
-LL |   let e: Example4::<7> = ();
-   |          -------------   ^^ expected struct `Example4`, found `()`
-   |          |
-   |          expected due to this
+LL |     let e: Example4::<7> = ();
+   |            -------------   ^^ expected struct `Example4`, found `()`
+   |            |
+   |            expected due to this
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/const-generics/defaults/needs-feature.rs b/src/test/ui/const-generics/defaults/needs-feature.rs
index 7eb7764a644..b58dee0712a 100644
--- a/src/test/ui/const-generics/defaults/needs-feature.rs
+++ b/src/test/ui/const-generics/defaults/needs-feature.rs
@@ -10,5 +10,5 @@ struct A<const N: usize, T=u32>(T);
 //[min]~^ ERROR type parameters must be declared prior
 
 fn main() {
-  let _: A<3> = A(0);
+    let _: A<3> = A(0);
 }
diff --git a/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs
new file mode 100644
index 00000000000..18ecf467299
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs
@@ -0,0 +1,14 @@
+// Regression test for #82792.
+
+// run-pass
+
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
+
+#[repr(C)]
+pub struct Loaf<T: Sized, const N: usize = 1usize> {
+    head: [T; N],
+    slice: [T],
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/simple-defaults.rs b/src/test/ui/const-generics/defaults/simple-defaults.rs
index 1f1b6c2260d..cb66c7769bb 100644
--- a/src/test/ui/const-generics/defaults/simple-defaults.rs
+++ b/src/test/ui/const-generics/defaults/simple-defaults.rs
@@ -6,12 +6,12 @@
 #![allow(dead_code)]
 
 struct FixedOutput<'a, const N: usize, T=u32> {
-  //[min]~^ ERROR type parameters must be declared prior to const parameters
-  out: &'a [T; N],
+    //[min]~^ ERROR type parameters must be declared prior to const parameters
+    out: &'a [T; N],
 }
 
 trait FixedOutputter {
-  fn out(&self) -> FixedOutput<'_, 10>;
+    fn out(&self) -> FixedOutput<'_, 10>;
 }
 
 fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-56445.full.stderr b/src/test/ui/const-generics/issues/issue-56445-1.full.stderr
index 61fba92c196..8416d64e1c2 100644
--- a/src/test/ui/const-generics/issues/issue-56445.full.stderr
+++ b/src/test/ui/const-generics/issues/issue-56445-1.full.stderr
@@ -1,5 +1,5 @@
 warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-56445.rs:3:27
+  --> $DIR/issue-56445-1.rs:3:27
    |
 LL | #![cfg_attr(full, feature(const_generics))]
    |                           ^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | #![cfg_attr(full, feature(const_generics))]
    = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
 
 error[E0771]: use of non-static lifetime `'a` in const generic
-  --> $DIR/issue-56445.rs:8:26
+  --> $DIR/issue-56445-1.rs:8:26
    |
 LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
    |                          ^^
diff --git a/src/test/ui/const-generics/issues/issue-56445.min.stderr b/src/test/ui/const-generics/issues/issue-56445-1.min.stderr
index 80702dd4bc3..f7056f27cb3 100644
--- a/src/test/ui/const-generics/issues/issue-56445.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-56445-1.min.stderr
@@ -1,5 +1,5 @@
 error[E0771]: use of non-static lifetime `'a` in const generic
-  --> $DIR/issue-56445.rs:8:26
+  --> $DIR/issue-56445-1.rs:8:26
    |
 LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
    |                          ^^
diff --git a/src/test/ui/const-generics/issues/issue-56445.rs b/src/test/ui/const-generics/issues/issue-56445-1.rs
index bc9e1dee853..bc9e1dee853 100644
--- a/src/test/ui/const-generics/issues/issue-56445.rs
+++ b/src/test/ui/const-generics/issues/issue-56445-1.rs
diff --git a/src/test/ui/const-generics/issues/issue-56445-2.rs b/src/test/ui/const-generics/issues/issue-56445-2.rs
new file mode 100644
index 00000000000..e078c8487c7
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-56445-2.rs
@@ -0,0 +1,11 @@
+// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-502095133
+struct OnDiskDirEntry<'a> { _s: &'a usize }
+
+impl<'a> OnDiskDirEntry<'a> {
+    const LFN_FRAGMENT_LEN: usize = 2;
+
+    fn lfn_contents(&self) -> [char; Self::LFN_FRAGMENT_LEN] { loop { } }
+    //~^ ERROR: generic `Self` types are currently not permitted in anonymous constants
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-56445-2.stderr b/src/test/ui/const-generics/issues/issue-56445-2.stderr
new file mode 100644
index 00000000000..770c80cbbd3
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-56445-2.stderr
@@ -0,0 +1,14 @@
+error: generic `Self` types are currently not permitted in anonymous constants
+  --> $DIR/issue-56445-2.rs:7:38
+   |
+LL |     fn lfn_contents(&self) -> [char; Self::LFN_FRAGMENT_LEN] { loop { } }
+   |                                      ^^^^
+   |
+note: not a concrete type
+  --> $DIR/issue-56445-2.rs:4:10
+   |
+LL | impl<'a> OnDiskDirEntry<'a> {
+   |          ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-56445-3.rs b/src/test/ui/const-generics/issues/issue-56445-3.rs
new file mode 100644
index 00000000000..c29df14586e
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-56445-3.rs
@@ -0,0 +1,12 @@
+// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-524494170
+pub struct Memory<'rom> {
+    rom: &'rom [u8],
+    ram: [u8; Self::SIZE],
+    //~^ ERROR: generic `Self` types are currently not permitted in anonymous constants
+}
+
+impl<'rom> Memory<'rom> {
+    pub const SIZE: usize = 0x8000;
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-56445-3.stderr b/src/test/ui/const-generics/issues/issue-56445-3.stderr
new file mode 100644
index 00000000000..f1c49eecfb5
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-56445-3.stderr
@@ -0,0 +1,8 @@
+error: generic `Self` types are currently not permitted in anonymous constants
+  --> $DIR/issue-56445-3.rs:4:15
+   |
+LL |     ram: [u8; Self::SIZE],
+   |               ^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-69654-run-pass.rs b/src/test/ui/const-generics/issues/issue-69654-run-pass.rs
index bbfd2183b06..45318ca68fc 100644
--- a/src/test/ui/const-generics/issues/issue-69654-run-pass.rs
+++ b/src/test/ui/const-generics/issues/issue-69654-run-pass.rs
@@ -1,4 +1,3 @@
-// run-pass
 #![feature(const_generics)]
 #![allow(incomplete_features, unused_braces)]
 
@@ -15,4 +14,5 @@ where
 
 fn main() {
     Foo::foo();
+    //~^ ERROR the function or associated item
 }
diff --git a/src/test/ui/const-generics/issues/issue-69654-run-pass.stderr b/src/test/ui/const-generics/issues/issue-69654-run-pass.stderr
new file mode 100644
index 00000000000..a82a60696b3
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-69654-run-pass.stderr
@@ -0,0 +1,15 @@
+error[E0599]: the function or associated item `foo` exists for struct `Foo<{_: usize}>`, but its trait bounds were not satisfied
+  --> $DIR/issue-69654-run-pass.rs:16:10
+   |
+LL | struct Foo<const N: usize> {}
+   | -------------------------- function or associated item `foo` not found for this
+...
+LL |     Foo::foo();
+   |          ^^^ function or associated item cannot be called on `Foo<{_: usize}>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `[u8; _]: Bar<[(); _]>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/const-generics/issues/issue-69654.rs b/src/test/ui/const-generics/issues/issue-69654.rs
index 7e775999ebd..b1214b12a14 100644
--- a/src/test/ui/const-generics/issues/issue-69654.rs
+++ b/src/test/ui/const-generics/issues/issue-69654.rs
@@ -15,4 +15,5 @@ where
 
 fn main() {
     Foo::foo();
+    //~^ ERROR the function or associated item
 }
diff --git a/src/test/ui/const-generics/issues/issue-69654.stderr b/src/test/ui/const-generics/issues/issue-69654.stderr
index 70af7bf25d8..0ce7640f685 100644
--- a/src/test/ui/const-generics/issues/issue-69654.stderr
+++ b/src/test/ui/const-generics/issues/issue-69654.stderr
@@ -4,6 +4,19 @@ error[E0423]: expected value, found type parameter `T`
 LL | impl<T> Bar<T> for [u8; T] {}
    |                         ^ not a value
 
-error: aborting due to previous error
+error[E0599]: the function or associated item `foo` exists for struct `Foo<{_: usize}>`, but its trait bounds were not satisfied
+  --> $DIR/issue-69654.rs:17:10
+   |
+LL | struct Foo<const N: usize> {}
+   | -------------------------- function or associated item `foo` not found for this
+...
+LL |     Foo::foo();
+   |          ^^^ function or associated item cannot be called on `Foo<{_: usize}>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `[u8; _]: Bar<[(); _]>`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0423`.
+Some errors have detailed explanations: E0423, E0599.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-1.rs b/src/test/ui/const-generics/occurs-check/unused-substs-1.rs
index f56687ecd93..6ded9f13bc4 100644
--- a/src/test/ui/const-generics/occurs-check/unused-substs-1.rs
+++ b/src/test/ui/const-generics/occurs-check/unused-substs-1.rs
@@ -1,4 +1,3 @@
-// build-pass
 #![feature(const_generics)]
 #![allow(incomplete_features)]
 
@@ -10,5 +9,5 @@ where
     A<N>: Bar<N>;
 
 fn main() {
-    let _ = A;
+    let _ = A; //~ERROR the trait bound
 }
diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr
new file mode 100644
index 00000000000..6830288acc0
--- /dev/null
+++ b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `A<{_: usize}>: Bar<{_: usize}>` is not satisfied
+  --> $DIR/unused-substs-1.rs:12:13
+   |
+LL | / struct A<const N: usize>
+LL | | where
+LL | |     A<N>: Bar<N>;
+   | |_________________- required by `A`
+...
+LL |       let _ = A;
+   |               ^ the trait `Bar<{_: usize}>` is not implemented for `A<{_: usize}>`
+   |
+   = help: the following implementations were found:
+             <A<7_usize> as Bar<N>>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-2.rs b/src/test/ui/const-generics/occurs-check/unused-substs-2.rs
index 12444ec5312..2d00141fbf7 100644
--- a/src/test/ui/const-generics/occurs-check/unused-substs-2.rs
+++ b/src/test/ui/const-generics/occurs-check/unused-substs-2.rs
@@ -1,4 +1,3 @@
-// check-pass
 #![feature(const_generics)]
 #![allow(incomplete_features)]
 
@@ -24,4 +23,6 @@ fn main() {
     // `t` is `ty::Infer(TyVar(_#1t))`
     // `foo` contains `ty::Infer(TyVar(_#1t))` in its substs
     t = foo;
+    //~^ ERROR mismatched types
+    //~| NOTE cyclic type
 }
diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-2.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-2.stderr
new file mode 100644
index 00000000000..9532fc21a31
--- /dev/null
+++ b/src/test/ui/const-generics/occurs-check/unused-substs-2.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/unused-substs-2.rs:25:9
+   |
+LL |     t = foo;
+   |         ^^^ cyclic type of infinite size
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-3.rs b/src/test/ui/const-generics/occurs-check/unused-substs-3.rs
index 187e27382fc..2e306f8c4c8 100644
--- a/src/test/ui/const-generics/occurs-check/unused-substs-3.rs
+++ b/src/test/ui/const-generics/occurs-check/unused-substs-3.rs
@@ -1,4 +1,3 @@
-// check-pass
 #![feature(const_generics)]
 #![allow(incomplete_features)]
 
@@ -15,4 +14,6 @@ fn main() {
     // `t` is `ty::Infer(TyVar(_#1t))`
     // `foo` contains `ty::Infer(TyVar(_#1t))` in its substs
     t = foo;
+    //~^ ERROR mismatched types
+    //~| NOTE cyclic type
 }
diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-3.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-3.stderr
new file mode 100644
index 00000000000..2551d68f974
--- /dev/null
+++ b/src/test/ui/const-generics/occurs-check/unused-substs-3.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/unused-substs-3.rs:16:9
+   |
+LL |     t = foo;
+   |         ^^^
+   |         |
+   |         cyclic type of infinite size
+   |         help: try using a conversion method: `foo.to_vec()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-4.rs b/src/test/ui/const-generics/occurs-check/unused-substs-4.rs
index 8e42ceb6d70..9c7f5ab91ed 100644
--- a/src/test/ui/const-generics/occurs-check/unused-substs-4.rs
+++ b/src/test/ui/const-generics/occurs-check/unused-substs-4.rs
@@ -1,4 +1,3 @@
-// build-pass
 #![feature(const_generics)]
 #![allow(incomplete_features)]
 
@@ -8,5 +7,5 @@ fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] {
 
 fn main() {
     let mut arr = Default::default();
-    arr = bind(arr);
+    arr = bind(arr); //~ ERROR mismatched type
 }
diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-4.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-4.stderr
new file mode 100644
index 00000000000..5685eedbdec
--- /dev/null
+++ b/src/test/ui/const-generics/occurs-check/unused-substs-4.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/unused-substs-4.rs:10:11
+   |
+LL |     arr = bind(arr);
+   |           ^^^^^^^^^ encountered a self-referencing constant
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.rs b/src/test/ui/consts/const-eval/conditional_array_execution.rs
index 9b99a685b63..bd517e568ea 100644
--- a/src/test/ui/consts/const-eval/conditional_array_execution.rs
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.rs
@@ -10,7 +10,7 @@ const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
 
 fn main() {
     println!("{}", FOO);
-    //~^ ERROR
+    //~^ ERROR evaluation of constant value failed
     //~| WARN erroneous constant used [const_err]
     //~| WARN this was previously accepted by the compiler but is being phased out
 }
diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr
index 6a205ce9787..e6fecef9fb3 100644
--- a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr
@@ -20,7 +20,7 @@ error[E0080]: evaluation of constant value failed
 LL |     let x: &'static i32 = &X;
    |                            ^ referenced constant has errors
 query stack during panic:
-#0 [normalize_generic_arg_after_erasing_regions] normalizing `main::promoted[1]`
+#0 [normalize_mir_const_after_erasing_regions] normalizing `main::promoted[1]`
 #1 [optimized_mir] optimizing MIR for `main`
 #2 [collect_and_partition_mono_items] collect_and_partition_mono_items
 end of query stack
diff --git a/src/test/ui/consts/const-eval/issue-44578.rs b/src/test/ui/consts/const-eval/issue-44578.rs
index 79f1301a2f9..a88e2197048 100644
--- a/src/test/ui/consts/const-eval/issue-44578.rs
+++ b/src/test/ui/consts/const-eval/issue-44578.rs
@@ -25,5 +25,5 @@ impl Foo for u16 {
 
 fn main() {
     println!("{}", <Bar<u16, u8> as Foo>::AMT);
-    //~^ ERROR evaluation of constant value failed [E0080]
+    //~^ ERROR evaluation of constant value failed
 }
diff --git a/src/test/ui/copy-a-resource.stderr b/src/test/ui/copy-a-resource.stderr
index 36cf57bd3c5..79095452f9d 100644
--- a/src/test/ui/copy-a-resource.stderr
+++ b/src/test/ui/copy-a-resource.stderr
@@ -6,14 +6,6 @@ LL | struct Foo {
 ...
 LL |     let _y = x.clone();
    |                ^^^^^ method not found in `Foo`
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<Foo>` here
-   |        the method is available for `Rc<Foo>` here
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
diff --git a/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs
index 0d11d933af0..a0ee3ad31e6 100644
--- a/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs
+++ b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs
@@ -1,7 +1,7 @@
 // Test that when a trait impl changes, fns whose body uses that trait
 // must also be recompiled.
 
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-assoc-type-codegen
 
 #![feature(rustc_attrs)]
 #![allow(warnings)]
diff --git a/src/test/ui/dep-graph/dep-graph-caller-callee.rs b/src/test/ui/dep-graph/dep-graph-caller-callee.rs
index b12c635d2e7..c95ea53650b 100644
--- a/src/test/ui/dep-graph/dep-graph-caller-callee.rs
+++ b/src/test/ui/dep-graph/dep-graph-caller-callee.rs
@@ -1,7 +1,7 @@
 // Test that immediate callers have to change when callee changes, but
 // not callers' callers.
 
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-caller-callee
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/dep-graph/dep-graph-struct-signature.rs b/src/test/ui/dep-graph/dep-graph-struct-signature.rs
index 7ef6fac48c3..50a670b8772 100644
--- a/src/test/ui/dep-graph/dep-graph-struct-signature.rs
+++ b/src/test/ui/dep-graph/dep-graph-struct-signature.rs
@@ -1,7 +1,7 @@
 // Test cases where a changing struct appears in the signature of fns
 // and methods.
 
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-struct-signature
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs
index 1b3bf5a3933..c0a6617316b 100644
--- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs
@@ -1,7 +1,7 @@
 // Test that adding an impl to a trait `Foo` DOES affect functions
 // that only use `Bar` if they have methods in common.
 
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-trait-impl-two-traits-same-method
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs
index ebfe8ccc3df..56e9762ddb2 100644
--- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs
@@ -1,7 +1,7 @@
 // Test that adding an impl to a trait `Foo` does not affect functions
 // that only use `Bar`, so long as they do not have methods in common.
 
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-trait-impl-two-traits
 
 #![feature(rustc_attrs)]
 #![allow(warnings)]
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl.rs b/src/test/ui/dep-graph/dep-graph-trait-impl.rs
index 9dd201e2a1f..3bbe3e745ca 100644
--- a/src/test/ui/dep-graph/dep-graph-trait-impl.rs
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl.rs
@@ -1,7 +1,7 @@
 // Test that when a trait impl changes, fns whose body uses that trait
 // must also be recompiled.
 
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-trait-impl
 
 #![feature(rustc_attrs)]
 #![allow(warnings)]
diff --git a/src/test/ui/dep-graph/dep-graph-type-alias.rs b/src/test/ui/dep-graph/dep-graph-type-alias.rs
index c9151ce79c5..5c5e24693a4 100644
--- a/src/test/ui/dep-graph/dep-graph-type-alias.rs
+++ b/src/test/ui/dep-graph/dep-graph-type-alias.rs
@@ -1,6 +1,6 @@
 // Test that changing what a `type` points to does not go unnoticed.
 
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-type-alias
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/dep-graph/dep-graph-variance-alias.rs b/src/test/ui/dep-graph/dep-graph-variance-alias.rs
index 927ea559778..6cc1f44104a 100644
--- a/src/test/ui/dep-graph/dep-graph-variance-alias.rs
+++ b/src/test/ui/dep-graph/dep-graph-variance-alias.rs
@@ -1,7 +1,7 @@
 // Test that changing what a `type` points to does not go unnoticed
 // by the variance analysis.
 
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-variance-alias
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
index ffee7004f8f..fd993d0f9d8 100644
--- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr
+++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
@@ -12,14 +12,6 @@ LL | struct NotClone;
 ...
 LL |     Bar::<NotClone> { x: 1 }.clone();
    |                              ^^^^^ method cannot be called on `Bar<NotClone>` due to unsatisfied trait bounds
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<Bar<NotClone>>` here
-   |        the method is available for `Rc<Bar<NotClone>>` here
    |
    = note: the following trait bounds were not satisfied:
            `NotClone: Clone`
diff --git a/src/test/ui/derives/deriving-with-repr-packed.rs b/src/test/ui/derives/deriving-with-repr-packed.rs
index d354cef66bc..b78eeaa9055 100644
--- a/src/test/ui/derives/deriving-with-repr-packed.rs
+++ b/src/test/ui/derives/deriving-with-repr-packed.rs
@@ -1,4 +1,4 @@
-#![deny(safe_packed_borrows)]
+#![deny(unaligned_references)]
 
 // check that derive on a packed struct with non-Copy fields
 // correctly. This can't be made to work perfectly because
diff --git a/src/test/ui/derives/deriving-with-repr-packed.stderr b/src/test/ui/derives/deriving-with-repr-packed.stderr
index d739257c8de..3caa563a085 100644
--- a/src/test/ui/derives/deriving-with-repr-packed.stderr
+++ b/src/test/ui/derives/deriving-with-repr-packed.stderr
@@ -7,10 +7,10 @@ LL | #[derive(Copy, Clone, PartialEq, Eq)]
 note: the lint level is defined here
   --> $DIR/deriving-with-repr-packed.rs:1:9
    |
-LL | #![deny(safe_packed_borrows)]
-   |         ^^^^^^^^^^^^^^^^^^^
+LL | #![deny(unaligned_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^
    = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133)
@@ -20,7 +20,7 @@ LL | #[derive(Copy, Clone, PartialEq, Eq)]
    |                       ^^^^^^^^^
    |
    = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
@@ -30,7 +30,7 @@ LL | #[derive(PartialEq, Eq)]
    |          ^^^^^^^^^
    |
    = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
@@ -40,7 +40,7 @@ LL | #[derive(PartialEq)]
    |          ^^^^^^^^^
    |
    = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 4 previous errors
diff --git a/src/test/ui/error-codes/E0106.stderr b/src/test/ui/error-codes/E0106.stderr
index ac70e887626..b961fc8aeeb 100644
--- a/src/test/ui/error-codes/E0106.stderr
+++ b/src/test/ui/error-codes/E0106.stderr
@@ -24,17 +24,6 @@ LL |     B(&'a bool),
    |
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/E0106.rs:10:14
-   |
-LL | type MyStr = &str;
-   |              ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL | type MyStr<'a> = &'a str;
-   |           ^^^^   ^^^
-
-error[E0106]: missing lifetime specifier
   --> $DIR/E0106.rs:17:10
    |
 LL |     baz: Baz,
@@ -61,6 +50,17 @@ LL |
 LL |     buzz: Buzz<'a, 'a>,
    |
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/E0106.rs:10:14
+   |
+LL | type MyStr = &str;
+   |              ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | type MyStr<'a> = &'a str;
+   |           ^^^^   ^^^
+
 error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/feature-gates/feature-gate-doc_notable_trait.rs b/src/test/ui/feature-gates/feature-gate-doc_notable_trait.rs
new file mode 100644
index 00000000000..7f3392eadad
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_notable_trait.rs
@@ -0,0 +1,4 @@
+#[doc(notable_trait)] //~ ERROR: `#[doc(notable_trait)]` is experimental
+trait SomeTrait {}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-doc_notable_trait.stderr b/src/test/ui/feature-gates/feature-gate-doc_notable_trait.stderr
new file mode 100644
index 00000000000..1f9bef40c4e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_notable_trait.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `#[doc(notable_trait)]` is experimental
+  --> $DIR/feature-gate-doc_notable_trait.rs:1:1
+   |
+LL | #[doc(notable_trait)]
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #45040 <https://github.com/rust-lang/rust/issues/45040> for more information
+   = help: add `#![feature(doc_notable_trait)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs b/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs
deleted file mode 100644
index 452b45b3445..00000000000
--- a/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#[doc(spotlight)] //~ ERROR: `#[doc(spotlight)]` is experimental
-trait SomeTrait {}
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr b/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr
deleted file mode 100644
index 010d74054a4..00000000000
--- a/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: `#[doc(spotlight)]` is experimental
-  --> $DIR/feature-gate-doc_spotlight.rs:1:1
-   |
-LL | #[doc(spotlight)]
-   | ^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #45040 <https://github.com/rust-lang/rust/issues/45040> for more information
-   = help: add `#![feature(doc_spotlight)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr b/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr
index 0f0406b8e17..497b8a429e0 100644
--- a/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr
+++ b/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr
@@ -1,3 +1,87 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:50:14
+   |
+LL | impl MyTrait<'a> for Y<&'a u8> {
+   |     -        ^^ undeclared lifetime
+   |     |
+   |     help: consider introducing lifetime `'a` here: `<'a>`
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:50:25
+   |
+LL | impl MyTrait<'a> for Y<&'a u8> {
+   |     -                   ^^ undeclared lifetime
+   |     |
+   |     help: consider introducing lifetime `'a` here: `<'a>`
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:53:31
+   |
+LL |     fn my_lifetime(&self) -> &'a u8 { self.0 }
+   |                               ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+help: consider introducing lifetime `'a` here
+   |
+LL | impl<'a> MyTrait<'a> for Y<&'a u8> {
+   |     ^^^^
+help: consider introducing lifetime `'a` here
+   |
+LL |     fn my_lifetime<'a>(&self) -> &'a u8 { self.0 }
+   |                   ^^^^
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:55:27
+   |
+LL |     fn any_lifetime() -> &'b u8 { &0 }
+   |                           ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
+   |     ^^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn any_lifetime<'b>() -> &'b u8 { &0 }
+   |                    ^^^^
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:57:27
+   |
+LL |     fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
+   |                           ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
+   |     ^^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 }
+   |                         ^^^^
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:57:40
+   |
+LL |     fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
+   |                                        ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
+   |     ^^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 }
+   |                         ^^^^
+
 error[E0261]: use of undeclared lifetime name `'x`
   --> $DIR/feature-gate-in_band_lifetimes.rs:3:12
    |
@@ -142,90 +226,6 @@ help: consider introducing lifetime `'b` here
 LL |     fn borrowed_lifetime<'b>(&'b self) -> &'b u8;
    |                         ^^^^
 
-error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/feature-gate-in_band_lifetimes.rs:50:14
-   |
-LL | impl MyTrait<'a> for Y<&'a u8> {
-   |     -        ^^ undeclared lifetime
-   |     |
-   |     help: consider introducing lifetime `'a` here: `<'a>`
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-
-error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/feature-gate-in_band_lifetimes.rs:50:25
-   |
-LL | impl MyTrait<'a> for Y<&'a u8> {
-   |     -                   ^^ undeclared lifetime
-   |     |
-   |     help: consider introducing lifetime `'a` here: `<'a>`
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-
-error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/feature-gate-in_band_lifetimes.rs:53:31
-   |
-LL |     fn my_lifetime(&self) -> &'a u8 { self.0 }
-   |                               ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-help: consider introducing lifetime `'a` here
-   |
-LL | impl<'a> MyTrait<'a> for Y<&'a u8> {
-   |     ^^^^
-help: consider introducing lifetime `'a` here
-   |
-LL |     fn my_lifetime<'a>(&self) -> &'a u8 { self.0 }
-   |                   ^^^^
-
-error[E0261]: use of undeclared lifetime name `'b`
-  --> $DIR/feature-gate-in_band_lifetimes.rs:55:27
-   |
-LL |     fn any_lifetime() -> &'b u8 { &0 }
-   |                           ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-help: consider introducing lifetime `'b` here
-   |
-LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
-   |     ^^^^
-help: consider introducing lifetime `'b` here
-   |
-LL |     fn any_lifetime<'b>() -> &'b u8 { &0 }
-   |                    ^^^^
-
-error[E0261]: use of undeclared lifetime name `'b`
-  --> $DIR/feature-gate-in_band_lifetimes.rs:57:27
-   |
-LL |     fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
-   |                           ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-help: consider introducing lifetime `'b` here
-   |
-LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
-   |     ^^^^
-help: consider introducing lifetime `'b` here
-   |
-LL |     fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 }
-   |                         ^^^^
-
-error[E0261]: use of undeclared lifetime name `'b`
-  --> $DIR/feature-gate-in_band_lifetimes.rs:57:40
-   |
-LL |     fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
-   |                                        ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-help: consider introducing lifetime `'b` here
-   |
-LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
-   |     ^^^^
-help: consider introducing lifetime `'b` here
-   |
-LL |     fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 }
-   |                         ^^^^
-
 error: aborting due to 17 previous errors
 
 For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr
index 30e23ea8f65..3f1f33a3b12 100644
--- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr
+++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr
@@ -16,10 +16,10 @@ error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-
   --> $DIR/type-mismatch-signature-deduction.rs:5:13
    |
 LL | fn foo() -> impl Generator<Return = i32> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `i32`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found enum `Result`
    |
-   = note: expected enum `Result<{integer}, _>`
-              found type `i32`
+   = note: expected type `i32`
+              found enum `Result<{integer}, _>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generic-associated-types/shadowing.stderr b/src/test/ui/generic-associated-types/shadowing.stderr
index 95cebbb8681..d45ef83873a 100644
--- a/src/test/ui/generic-associated-types/shadowing.stderr
+++ b/src/test/ui/generic-associated-types/shadowing.stderr
@@ -15,14 +15,6 @@ LL |     type Bar<T> = i32;
    |              ^ already used
 
 error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
-  --> $DIR/shadowing.rs:5:14
-   |
-LL | trait Shadow<'a> {
-   |              -- first declared here
-LL |     type Bar<'a>;
-   |              ^^ lifetime `'a` already in scope
-
-error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
   --> $DIR/shadowing.rs:14:14
    |
 LL | impl<'a> NoShadow<'a> for &'a u32 {
@@ -30,6 +22,14 @@ LL | impl<'a> NoShadow<'a> for &'a u32 {
 LL |     type Bar<'a> = i32;
    |              ^^ lifetime `'a` already in scope
 
+error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
+  --> $DIR/shadowing.rs:5:14
+   |
+LL | trait Shadow<'a> {
+   |              -- first declared here
+LL |     type Bar<'a>;
+   |              ^^ lifetime `'a` already in scope
+
 error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0403, E0496.
diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
index 1106a067822..ce853d4d36d 100644
--- a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
+++ b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
@@ -5,6 +5,17 @@ LL | fn should_error<T>() where T : Into<&u32> {}
    |                                     ^ explicit lifetime name needed here
 
 error[E0106]: missing lifetime specifier
+  --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:13:17
+   |
+LL | fn bar<'b, L: X<&'b Nested<i32>>>(){}
+   |                 ^ expected named lifetime parameter
+   |
+help: consider using the `'b` lifetime
+   |
+LL | fn bar<'b, L: X<'b, &'b Nested<i32>>>(){}
+   |                 ^^^
+
+error[E0106]: missing lifetime specifier
   --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:21
    |
 LL |     fn foo<'b, L: X<&'b Nested<K>>>();
@@ -22,17 +33,6 @@ help: consider using one of the available lifetimes here
 LL |     fn foo<'b, L: X<'lifetime, &'b Nested<K>>>();
    |                     ^^^^^^^^^^
 
-error[E0106]: missing lifetime specifier
-  --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:13:17
-   |
-LL | fn bar<'b, L: X<&'b Nested<i32>>>(){}
-   |                 ^ expected named lifetime parameter
-   |
-help: consider using the `'b` lifetime
-   |
-LL | fn bar<'b, L: X<'b, &'b Nested<i32>>>(){}
-   |                 ^^^
-
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0106, E0637.
diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr
index 73bd76aa5fa..94fdd355d48 100644
--- a/src/test/ui/generics/wrong-number-of-args.stderr
+++ b/src/test/ui/generics/wrong-number-of-args.stderr
@@ -1,36 +1,3 @@
-error[E0106]: missing lifetime specifier
-  --> $DIR/wrong-number-of-args.rs:44:14
-   |
-LL |     type A = Ty;
-   |              ^^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |     type A<'a> = Ty<'a>;
-   |           ^^^^   ^^^^^^
-
-error[E0106]: missing lifetime specifier
-  --> $DIR/wrong-number-of-args.rs:54:17
-   |
-LL |     type C = Ty<usize>;
-   |                 ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |     type C<'a> = Ty<'a, usize>;
-   |           ^^^^      ^^^
-
-error[E0106]: missing lifetime specifier
-  --> $DIR/wrong-number-of-args.rs:100:22
-   |
-LL |     type B = Box<dyn GenericLifetime>;
-   |                      ^^^^^^^^^^^^^^^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |     type B<'a> = Box<dyn GenericLifetime<'a>>;
-   |           ^^^^           ^^^^^^^^^^^^^^^^^^^
-
 error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/wrong-number-of-args.rs:6:14
    |
@@ -165,6 +132,17 @@ help: use angle brackets to add missing type argument
 LL |     type A = Ty<T>;
    |                ^^^
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:44:14
+   |
+LL |     type A = Ty;
+   |              ^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type A<'a> = Ty<'a>;
+   |           ^^^^   ^^^^^^
+
 error[E0107]: this struct takes 1 type argument but 0 type arguments were supplied
   --> $DIR/wrong-number-of-args.rs:50:14
    |
@@ -181,6 +159,17 @@ help: add missing type argument
 LL |     type B = Ty<'static, T>;
    |                        ^^^
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:54:17
+   |
+LL |     type C = Ty<usize>;
+   |                 ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type C<'a> = Ty<'a, usize>;
+   |           ^^^^      ^^^
+
 error[E0107]: missing generics for struct `type_and_type_and_type::Ty`
   --> $DIR/wrong-number-of-args.rs:64:14
    |
@@ -243,6 +232,17 @@ note: trait defined here, with 0 type parameters
 LL |     trait NonGeneric {
    |           ^^^^^^^^^^
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:100:22
+   |
+LL |     type B = Box<dyn GenericLifetime>;
+   |                      ^^^^^^^^^^^^^^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type B<'a> = Box<dyn GenericLifetime<'a>>;
+   |           ^^^^           ^^^^^^^^^^^^^^^^^^^
+
 error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
   --> $DIR/wrong-number-of-args.rs:104:22
    |
diff --git a/src/test/ui/hrtb/complex.rs b/src/test/ui/hrtb/complex.rs
new file mode 100644
index 00000000000..8cdfe247e02
--- /dev/null
+++ b/src/test/ui/hrtb/complex.rs
@@ -0,0 +1,28 @@
+// check-pass
+
+trait A<'a> {}
+trait B<'b> {}
+fn foo<T>() where for<'a> T: A<'a> + 'a {}
+trait C<'c>: for<'a> A<'a> + for<'b> B<'b> {
+    type As;
+}
+struct D<T> where T: for<'c> C<'c, As=&'c ()> {
+    t: std::marker::PhantomData<T>,
+}
+trait E<'e, 'g> {
+    type As;
+}
+trait F<'f>: for<'a> A<'a> + for<'e> E<'e, 'f> {}
+struct G<T> where T: for<'f> F<'f, As=&'f ()> {
+    t: std::marker::PhantomData<T>,
+}
+trait H<'a, 'b> {
+    type As;
+}
+trait I<'a>: for<'b> H<'a, 'b> {}
+
+struct J<T> where T: for<'i> I<'i, As=&'i ()> {
+    t: std::marker::PhantomData<T>,
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr
index a7d06c71663..6958cd97a4a 100644
--- a/src/test/ui/impl-trait/bound-normalization-fail.stderr
+++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr
@@ -11,10 +11,10 @@ error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as imp
   --> $DIR/bound-normalization-fail.rs:27:32
    |
 LL |     fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> {
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()`
    |
-   = note:         expected type `()`
-           found associated type `<T as impl_trait::Trait>::Assoc`
+   = note: expected associated type `<T as impl_trait::Trait>::Assoc`
+                         found type `()`
 help: consider constraining the associated type `<T as impl_trait::Trait>::Assoc` to `()`
    |
 LL |     fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output=T::Assoc> {
@@ -30,10 +30,10 @@ error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lif
   --> $DIR/bound-normalization-fail.rs:43:41
    |
 LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
-   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()`
    |
-   = note:         expected type `()`
-           found associated type `<T as lifetimes::Trait<'static>>::Assoc`
+   = note: expected associated type `<T as lifetimes::Trait<'static>>::Assoc`
+                         found type `()`
 help: consider constraining the associated type `<T as lifetimes::Trait<'static>>::Assoc` to `()`
    |
 LL |     fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output=T::Assoc> {
diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr
index 1443b76048b..3318866c52c 100644
--- a/src/test/ui/impl-trait/equality2.stderr
+++ b/src/test/ui/impl-trait/equality2.stderr
@@ -35,8 +35,10 @@ LL |     let _: i32 = Leak::leak(hide(0_i32));
    |
    = note:         expected type `i32`
            found associated type `<impl Foo as Leak>::T`
-   = help: consider constraining the associated type `<impl Foo as Leak>::T` to `i32`
-   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+help: consider constraining the associated type `<impl Foo as Leak>::T` to `i32`
+   |
+LL | fn hide<T: Foo>(x: T) -> impl Foo<T = i32> {
+   |                                  ^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/equality2.rs:38:10
diff --git a/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr b/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr
index bd4d4fdf2a6..8e42b9d46db 100644
--- a/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr
+++ b/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr
@@ -2,13 +2,13 @@ error[E0271]: type mismatch resolving `<Bar as Iterator>::Item == Box<(dyn for<'
   --> $DIR/issue-70877.rs:11:12
    |
 LL | type FooRet = impl std::fmt::Debug;
-   |               -------------------- the expected opaque type
+   |               -------------------- the found opaque type
 ...
 LL | type Foo = impl Iterator<Item = FooItem>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found enum `Option`
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found opaque type
    |
-   = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>`
-              found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
+   = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
+              found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr b/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr
index bd4d4fdf2a6..8e42b9d46db 100644
--- a/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr
+++ b/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr
@@ -2,13 +2,13 @@ error[E0271]: type mismatch resolving `<Bar as Iterator>::Item == Box<(dyn for<'
   --> $DIR/issue-70877.rs:11:12
    |
 LL | type FooRet = impl std::fmt::Debug;
-   |               -------------------- the expected opaque type
+   |               -------------------- the found opaque type
 ...
 LL | type Foo = impl Iterator<Item = FooItem>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found enum `Option`
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found opaque type
    |
-   = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>`
-              found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
+   = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
+              found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs
new file mode 100644
index 00000000000..b4fd6b3e743
--- /dev/null
+++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs
@@ -0,0 +1,20 @@
+pub trait Super {
+    type Assoc;
+}
+
+impl Super for () {
+    type Assoc = u8;
+}
+
+pub trait Test {}
+
+impl<T> Test for T where T: Super<Assoc = ()> {}
+
+fn test() -> impl Test {
+    //~^ERROR type mismatch resolving `<() as Super>::Assoc == ()`
+    ()
+}
+
+fn main() {
+    let a = test();
+}
diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr
new file mode 100644
index 00000000000..d1956a9afb8
--- /dev/null
+++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr
@@ -0,0 +1,11 @@
+error[E0271]: type mismatch resolving `<() as Super>::Assoc == ()`
+  --> $DIR/projection-mismatch-in-impl-where-clause.rs:13:14
+   |
+LL | fn test() -> impl Test {
+   |              ^^^^^^^^^ expected `()`, found `u8`
+   |
+   = note: required because of the requirements on the impl of `Test` for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/inference/issue-83606.rs b/src/test/ui/inference/issue-83606.rs
new file mode 100644
index 00000000000..be56a3020cc
--- /dev/null
+++ b/src/test/ui/inference/issue-83606.rs
@@ -0,0 +1,10 @@
+// Regression test for #83606.
+
+fn foo<const N: usize>(_: impl std::fmt::Display) -> [usize; N] {
+    [0; N]
+}
+
+fn main() {
+    let _ = foo("foo"); //<- Do not suggest `foo::<N>("foo");`!
+    //~^ ERROR: type annotations needed for `[usize; _]`
+}
diff --git a/src/test/ui/inference/issue-83606.stderr b/src/test/ui/inference/issue-83606.stderr
new file mode 100644
index 00000000000..65f3336b935
--- /dev/null
+++ b/src/test/ui/inference/issue-83606.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed for `[usize; _]`
+  --> $DIR/issue-83606.rs:8:13
+   |
+LL |     let _ = foo("foo"); //<- Do not suggest `foo::<N>("foo");`!
+   |         -   ^^^ cannot infer the value of const parameter `N` declared on the function `foo`
+   |         |
+   |         consider giving this pattern the explicit type `[usize; _]`, where the type parameter `N` is specified
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issue-83639.rs b/src/test/ui/issue-83639.rs
new file mode 100644
index 00000000000..6ddbedfa0bc
--- /dev/null
+++ b/src/test/ui/issue-83639.rs
@@ -0,0 +1,6 @@
+// check-fail
+// ignore-tidy-tab
+
+fn main() {
+    """	" //~ ERROR
+}
diff --git a/src/test/ui/issue-83639.stderr b/src/test/ui/issue-83639.stderr
new file mode 100644
index 00000000000..4c10df1917c
--- /dev/null
+++ b/src/test/ui/issue-83639.stderr
@@ -0,0 +1,8 @@
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `"    "`
+  --> $DIR/issue-83639.rs:5:7
+   |
+LL |     """    "
+   |       ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-27060-rpass.rs b/src/test/ui/issues/issue-27060-rpass.rs
index b20d614b303..d9159f6669d 100644
--- a/src/test/ui/issues/issue-27060-rpass.rs
+++ b/src/test/ui/issues/issue-27060-rpass.rs
@@ -8,14 +8,12 @@ pub struct Good {
 }
 
 // kill this test when that turns to a hard error
-#[allow(safe_packed_borrows)]
+#[allow(unaligned_references)]
 fn main() {
     let good = Good { data: &0, data2: [&0, &0], aligned: [0; 32] };
 
-    unsafe {
-        let _ = &good.data; // ok
-        let _ = &good.data2[0]; // ok
-    }
+    let _ = &good.data; // ok
+    let _ = &good.data2[0]; // ok
 
     let _ = &good.data;
     let _ = &good.data2[0];
diff --git a/src/test/ui/issues/issue-27060.rs b/src/test/ui/issues/issue-27060.rs
index 78f2022ed38..5317a616719 100644
--- a/src/test/ui/issues/issue-27060.rs
+++ b/src/test/ui/issues/issue-27060.rs
@@ -5,7 +5,7 @@ pub struct Good {
     aligned: [u8; 32],
 }
 
-#[deny(safe_packed_borrows)]
+#[deny(unaligned_references)]
 fn main() {
     let good = Good {
         data: &0,
@@ -13,14 +13,14 @@ fn main() {
         aligned: [0; 32]
     };
 
-    unsafe {
-        let _ = &good.data; // ok
-        let _ = &good.data2[0]; // ok
-    }
+    let _ = &good.data; //~ ERROR reference to packed field
+    //~| hard error
+    let _ = &good.data2[0]; //~ ERROR reference to packed field
+    //~| hard error
 
-    let _ = &good.data; //~ ERROR borrow of packed field is unsafe
+    let _ = &good.data; //~ ERROR reference to packed field
                         //~| hard error
-    let _ = &good.data2[0]; //~ ERROR borrow of packed field is unsafe
+    let _ = &good.data2[0]; //~ ERROR reference to packed field
                             //~| hard error
     let _ = &*good.data; // ok, behind a pointer
     let _ = &good.aligned; // ok, has align 1
diff --git a/src/test/ui/issues/issue-27060.stderr b/src/test/ui/issues/issue-27060.stderr
index d14ae4d41d5..09297884ed3 100644
--- a/src/test/ui/issues/issue-27060.stderr
+++ b/src/test/ui/issues/issue-27060.stderr
@@ -1,5 +1,5 @@
-error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
-  --> $DIR/issue-27060.rs:21:13
+error: reference to packed field is unaligned
+  --> $DIR/issue-27060.rs:16:13
    |
 LL |     let _ = &good.data;
    |             ^^^^^^^^^^
@@ -7,21 +7,41 @@ LL |     let _ = &good.data;
 note: the lint level is defined here
   --> $DIR/issue-27060.rs:8:8
    |
-LL | #[deny(safe_packed_borrows)]
-   |        ^^^^^^^^^^^^^^^^^^^
+LL | #[deny(unaligned_references)]
+   |        ^^^^^^^^^^^^^^^^^^^^
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+
+error: reference to packed field is unaligned
+  --> $DIR/issue-27060.rs:18:13
+   |
+LL |     let _ = &good.data2[0];
+   |             ^^^^^^^^^^^^^^
+   |
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+
+error: reference to packed field is unaligned
+  --> $DIR/issue-27060.rs:21:13
+   |
+LL |     let _ = &good.data;
+   |             ^^^^^^^^^^
+   |
    = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
-   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
 
-error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
+error: reference to packed field is unaligned
   --> $DIR/issue-27060.rs:23:13
    |
 LL |     let _ = &good.data2[0];
    |             ^^^^^^^^^^^^^^
    |
    = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
-   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-2823.stderr b/src/test/ui/issues/issue-2823.stderr
index e044352e954..b3bc946292f 100644
--- a/src/test/ui/issues/issue-2823.stderr
+++ b/src/test/ui/issues/issue-2823.stderr
@@ -6,14 +6,6 @@ LL | struct C {
 ...
 LL |     let _d = c.clone();
    |                ^^^^^ method not found in `C`
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<C>` here
-   |        the method is available for `Rc<C>` here
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr
index e91dae08b3a..043658c9508 100644
--- a/src/test/ui/issues/issue-33941.stderr
+++ b/src/test/ui/issues/issue-33941.stderr
@@ -11,10 +11,10 @@ error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _,
   --> $DIR/issue-33941.rs:4:14
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found tuple
    |
-   = note:  expected tuple `(&_, &_)`
-           found reference `&_`
+   = note: expected reference `&_`
+                  found tuple `(&_, &_)`
    = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
    = note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
    = note: required by `into_iter`
@@ -23,10 +23,10 @@ error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _,
   --> $DIR/issue-33941.rs:4:14
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found tuple
    |
-   = note:  expected tuple `(&_, &_)`
-           found reference `&_`
+   = note: expected reference `&_`
+                  found tuple `(&_, &_)`
    = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
    = note: required by `std::iter::Iterator::next`
 
diff --git a/src/test/ui/issues/issue-39970.stderr b/src/test/ui/issues/issue-39970.stderr
index 6f342b459c0..8ecde9d1e68 100644
--- a/src/test/ui/issues/issue-39970.stderr
+++ b/src/test/ui/issues/issue-39970.stderr
@@ -5,7 +5,7 @@ LL |     fn visit() {}
    |     ---------- required by `Visit::visit`
 ...
 LL |     <() as Visit>::visit();
-   |     ^^^^^^^^^^^^^^^^^^^^ expected `&()`, found `()`
+   |     ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&()`
    |
    = note: required because of the requirements on the impl of `Visit` for `()`
 
diff --git a/src/test/ui/issues/issue-69725.stderr b/src/test/ui/issues/issue-69725.stderr
index 48c71d76af0..4dd6b4bbb68 100644
--- a/src/test/ui/issues/issue-69725.stderr
+++ b/src/test/ui/issues/issue-69725.stderr
@@ -8,14 +8,6 @@ LL |     let _ = Struct::<A>::new().clone();
    |
 LL | pub struct Struct<A>(A);
    | ------------------------ doesn't satisfy `Struct<A>: Clone`
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<Struct<A>>` here
-   |        the method is available for `Rc<Struct<A>>` here
    |
    = note: the following trait bounds were not satisfied:
            `A: Clone`
diff --git a/src/test/ui/iterators/array-of-ranges.stderr b/src/test/ui/iterators/array-of-ranges.stderr
index 601983a6153..7d58eb948ea 100644
--- a/src/test/ui/iterators/array-of-ranges.stderr
+++ b/src/test/ui/iterators/array-of-ranges.stderr
@@ -13,10 +13,10 @@ error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator
   --> $DIR/array-of-ranges.rs:4:14
    |
 LL |     for _ in [0..=1] {}
-   |              ^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it
+   |              ^^^^^^^ if you meant to iterate between two values, remove the square brackets
    |
    = help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]`
-   = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: `[start..=end]` is an array of one `RangeInclusive`; you might have meant to have a `RangeInclusive` without the brackets: `start..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]`
    = note: required by `into_iter`
 
@@ -24,10 +24,10 @@ error[E0277]: `[RangeFrom<{integer}>; 1]` is not an iterator
   --> $DIR/array-of-ranges.rs:6:14
    |
 LL |     for _ in [0..] {}
-   |              ^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it
+   |              ^^^^^ if you meant to iterate from a value onwards, remove the square brackets
    |
    = help: the trait `Iterator` is not implemented for `[RangeFrom<{integer}>; 1]`
-   = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: `[start..]` is an array of one `RangeFrom`; you might have meant to have a `RangeFrom` without the brackets: `start..`, keeping in mind that iterating over an unbounded iterator will run forever unless you `break` or `return` from within the loop
    = note: required because of the requirements on the impl of `IntoIterator` for `[RangeFrom<{integer}>; 1]`
    = note: required by `into_iter`
 
@@ -35,10 +35,10 @@ error[E0277]: `[RangeTo<{integer}>; 1]` is not an iterator
   --> $DIR/array-of-ranges.rs:8:14
    |
 LL |     for _ in [..1] {}
-   |              ^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it
+   |              ^^^^^ if you meant to iterate until a value, remove the square brackets and add a starting value
    |
    = help: the trait `Iterator` is not implemented for `[RangeTo<{integer}>; 1]`
-   = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: `[..end]` is an array of one `RangeTo`; you might have meant to have a bounded `Range` without the brackets: `0..end`
    = note: required because of the requirements on the impl of `IntoIterator` for `[RangeTo<{integer}>; 1]`
    = note: required by `into_iter`
 
@@ -46,10 +46,10 @@ error[E0277]: `[RangeToInclusive<{integer}>; 1]` is not an iterator
   --> $DIR/array-of-ranges.rs:10:14
    |
 LL |     for _ in [..=1] {}
-   |              ^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it
+   |              ^^^^^^ if you meant to iterate until a value (including it), remove the square brackets and add a starting value
    |
    = help: the trait `Iterator` is not implemented for `[RangeToInclusive<{integer}>; 1]`
-   = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: `[..=end]` is an array of one `RangeToInclusive`; you might have meant to have a bounded `RangeInclusive` without the brackets: `0..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `[RangeToInclusive<{integer}>; 1]`
    = note: required by `into_iter`
 
@@ -79,10 +79,10 @@ error[E0277]: `[std::ops::Range<{integer}>; 2]` is not an iterator
   --> $DIR/array-of-ranges.rs:19:14
    |
 LL |     for _ in [0..1, 2..3] {}
-   |              ^^^^^^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it
+   |              ^^^^^^^^^^^^ arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)`
    |
    = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 2]`
-   = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: see <https://github.com/rust-lang/rust/pull/65819> for more details
    = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 2]`
    = note: required by `into_iter`
 
@@ -90,10 +90,10 @@ error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator
   --> $DIR/array-of-ranges.rs:21:14
    |
 LL |     for _ in [0..=1] {}
-   |              ^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it
+   |              ^^^^^^^ if you meant to iterate between two values, remove the square brackets
    |
    = help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]`
-   = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: `[start..=end]` is an array of one `RangeInclusive`; you might have meant to have a `RangeInclusive` without the brackets: `start..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]`
    = note: required by `into_iter`
 
diff --git a/src/test/ui/iterators/array.stderr b/src/test/ui/iterators/array.stderr
index 68c6de5493f..7e2b600fb7a 100644
--- a/src/test/ui/iterators/array.stderr
+++ b/src/test/ui/iterators/array.stderr
@@ -2,10 +2,10 @@ error[E0277]: `[{integer}; 2]` is not an iterator
   --> $DIR/array.rs:2:14
    |
 LL |     for _ in [1, 2] {}
-   |              ^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it
+   |              ^^^^^^ arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)`
    |
    = help: the trait `Iterator` is not implemented for `[{integer}; 2]`
-   = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: see <https://github.com/rust-lang/rust/pull/65819> for more details
    = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]`
    = note: required by `into_iter`
 
@@ -13,10 +13,10 @@ error[E0277]: `[{integer}; 2]` is not an iterator
   --> $DIR/array.rs:5:14
    |
 LL |     for _ in x {}
-   |              ^ borrow the array with `&` or call `.iter()` on it to iterate over it
+   |              ^ arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)`
    |
    = help: the trait `Iterator` is not implemented for `[{integer}; 2]`
-   = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: see <https://github.com/rust-lang/rust/pull/65819> for more details
    = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]`
    = note: required by `into_iter`
 
@@ -24,10 +24,10 @@ error[E0277]: `[{float}; 2]` is not an iterator
   --> $DIR/array.rs:7:14
    |
 LL |     for _ in [1.0, 2.0] {}
-   |              ^^^^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it
+   |              ^^^^^^^^^^ arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)`
    |
    = help: the trait `Iterator` is not implemented for `[{float}; 2]`
-   = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: see <https://github.com/rust-lang/rust/pull/65819> for more details
    = note: required because of the requirements on the impl of `IntoIterator` for `[{float}; 2]`
    = note: required by `into_iter`
 
diff --git a/src/test/ui/iterators/ranges.stderr b/src/test/ui/iterators/ranges.stderr
index 4678bafd196..73844329e36 100644
--- a/src/test/ui/iterators/ranges.stderr
+++ b/src/test/ui/iterators/ranges.stderr
@@ -2,9 +2,10 @@ error[E0277]: `RangeTo<{integer}>` is not an iterator
   --> $DIR/ranges.rs:2:14
    |
 LL |     for _ in ..10 {}
-   |              ^^^^ `RangeTo<{integer}>` is not an iterator
+   |              ^^^^ if you meant to iterate until a value, add a starting value
    |
    = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>`
+   = note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end`
    = note: required because of the requirements on the impl of `IntoIterator` for `RangeTo<{integer}>`
    = note: required by `into_iter`
 
@@ -12,9 +13,10 @@ error[E0277]: `RangeToInclusive<{integer}>` is not an iterator
   --> $DIR/ranges.rs:4:14
    |
 LL |     for _ in ..=10 {}
-   |              ^^^^^ `RangeToInclusive<{integer}>` is not an iterator
+   |              ^^^^^ if you meant to iterate until a value (including it), add a starting value
    |
    = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>`
+   = note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end`
    = note: required because of the requirements on the impl of `IntoIterator` for `RangeToInclusive<{integer}>`
    = note: required by `into_iter`
 
diff --git a/src/test/ui/iterators/string.stderr b/src/test/ui/iterators/string.stderr
index 16530066824..1d77bcb7536 100644
--- a/src/test/ui/iterators/string.stderr
+++ b/src/test/ui/iterators/string.stderr
@@ -2,7 +2,7 @@ error[E0277]: `String` is not an iterator
   --> $DIR/string.rs:2:14
    |
 LL |     for _ in "".to_owned() {}
-   |              ^^^^^^^^^^^^^ `String` is not an iterator
+   |              ^^^^^^^^^^^^^ `String` is not an iterator; try calling `.chars()` or `.bytes()`
    |
    = help: the trait `Iterator` is not implemented for `String`
    = note: required because of the requirements on the impl of `IntoIterator` for `String`
diff --git a/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr b/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr
index 30142e24cd5..16333a7ca38 100644
--- a/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr
+++ b/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr
@@ -1,4 +1,14 @@
 error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
+   |
+LL | struct Test {
+   |            - help: consider introducing lifetime `'b` here: `<'b>`
+LL |     a: &'b str,
+   |         ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
+error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:13:13
    |
 LL |     fn foo(&'b self) {}
@@ -17,16 +27,6 @@ LL |     fn foo<'b>(&'b self) {}
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
    |
-LL | struct Test {
-   |            - help: consider introducing lifetime `'b` here: `<'b>`
-LL |     a: &'b str,
-   |         ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-
-error[E0261]: use of undeclared lifetime name `'b`
-  --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
-   |
 LL | #[derive(Eq, PartialEq)]
    |          -- lifetime `'b` is missing in item created through this procedural macro
 LL | struct Test {
diff --git a/src/test/ui/lint/unaligned_references.rs b/src/test/ui/lint/unaligned_references.rs
index c4e5d065643..d06b06b504f 100644
--- a/src/test/ui/lint/unaligned_references.rs
+++ b/src/test/ui/lint/unaligned_references.rs
@@ -8,22 +8,43 @@ pub struct Good {
     aligned: [u8; 32],
 }
 
+#[repr(packed(2))]
+pub struct Packed2 {
+    x: u32,
+    y: u16,
+    z: u8,
+}
+
 fn main() {
     unsafe {
         let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] };
 
         let _ = &good.ptr; //~ ERROR reference to packed field
+        //~^ previously accepted
         let _ = &good.data; //~ ERROR reference to packed field
+        //~^ previously accepted
         // Error even when turned into raw pointer immediately.
         let _ = &good.data as *const _; //~ ERROR reference to packed field
+        //~^ previously accepted
         let _: *const _ = &good.data; //~ ERROR reference to packed field
+        //~^ previously accepted
         // Error on method call.
         let _ = good.data.clone(); //~ ERROR reference to packed field
+        //~^ previously accepted
         // Error for nested fields.
         let _ = &good.data2[0]; //~ ERROR reference to packed field
+        //~^ previously accepted
 
         let _ = &*good.ptr; // ok, behind a pointer
         let _ = &good.aligned; // ok, has align 1
         let _ = &good.aligned[2]; // ok, has align 1
     }
+
+    unsafe {
+        let packed2 = Packed2 { x: 0, y: 0, z: 0 };
+        let _ = &packed2.x; //~ ERROR reference to packed field
+        //~^ previously accepted
+        let _ = &packed2.y; // ok, has align 2 in packed(2) struct
+        let _ = &packed2.z; // ok, has align 1
+    }
 }
diff --git a/src/test/ui/lint/unaligned_references.stderr b/src/test/ui/lint/unaligned_references.stderr
index 8786b9c05db..b4cce3cfea2 100644
--- a/src/test/ui/lint/unaligned_references.stderr
+++ b/src/test/ui/lint/unaligned_references.stderr
@@ -1,5 +1,5 @@
 error: reference to packed field is unaligned
-  --> $DIR/unaligned_references.rs:15:17
+  --> $DIR/unaligned_references.rs:22:17
    |
 LL |         let _ = &good.ptr;
    |                 ^^^^^^^^^
@@ -9,47 +9,69 @@ note: the lint level is defined here
    |
 LL | #![deny(unaligned_references)]
    |         ^^^^^^^^^^^^^^^^^^^^
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
 
 error: reference to packed field is unaligned
-  --> $DIR/unaligned_references.rs:16:17
+  --> $DIR/unaligned_references.rs:24:17
    |
 LL |         let _ = &good.data;
    |                 ^^^^^^^^^^
    |
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
 
 error: reference to packed field is unaligned
-  --> $DIR/unaligned_references.rs:18:17
+  --> $DIR/unaligned_references.rs:27:17
    |
 LL |         let _ = &good.data as *const _;
    |                 ^^^^^^^^^^
    |
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
 
 error: reference to packed field is unaligned
-  --> $DIR/unaligned_references.rs:19:27
+  --> $DIR/unaligned_references.rs:29:27
    |
 LL |         let _: *const _ = &good.data;
    |                           ^^^^^^^^^^
    |
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
 
 error: reference to packed field is unaligned
-  --> $DIR/unaligned_references.rs:21:17
+  --> $DIR/unaligned_references.rs:32:17
    |
 LL |         let _ = good.data.clone();
    |                 ^^^^^^^^^
    |
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
 
 error: reference to packed field is unaligned
-  --> $DIR/unaligned_references.rs:23:17
+  --> $DIR/unaligned_references.rs:35:17
    |
 LL |         let _ = &good.data2[0];
    |                 ^^^^^^^^^^^^^^
    |
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
 
-error: aborting due to 6 previous errors
+error: reference to packed field is unaligned
+  --> $DIR/unaligned_references.rs:45:17
+   |
+LL |         let _ = &packed2.x;
+   |                 ^^^^^^^^^^
+   |
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/lint/unaligned_references_external_macro.rs b/src/test/ui/lint/unaligned_references_external_macro.rs
index 6ac501fb0e0..cb597c38e77 100644
--- a/src/test/ui/lint/unaligned_references_external_macro.rs
+++ b/src/test/ui/lint/unaligned_references_external_macro.rs
@@ -1,10 +1,9 @@
 // aux-build:unaligned_references_external_crate.rs
 
-#![allow(safe_packed_borrows)]
-
 extern crate unaligned_references_external_crate;
 
 unaligned_references_external_crate::mac! { //~ERROR reference to packed field is unaligned
+    //~^ previously accepted
     #[repr(packed)]
     pub struct X {
         pub field: u16
diff --git a/src/test/ui/lint/unaligned_references_external_macro.stderr b/src/test/ui/lint/unaligned_references_external_macro.stderr
index 140294b65cc..4e7c6bfc98d 100644
--- a/src/test/ui/lint/unaligned_references_external_macro.stderr
+++ b/src/test/ui/lint/unaligned_references_external_macro.stderr
@@ -1,7 +1,8 @@
 error: reference to packed field is unaligned
-  --> $DIR/unaligned_references_external_macro.rs:7:1
+  --> $DIR/unaligned_references_external_macro.rs:5:1
    |
 LL | / unaligned_references_external_crate::mac! {
+LL | |
 LL | |     #[repr(packed)]
 LL | |     pub struct X {
 LL | |         pub field: u16
@@ -10,15 +11,18 @@ LL | | }
    | |_^
    |
 note: the lint level is defined here
-  --> $DIR/unaligned_references_external_macro.rs:7:1
+  --> $DIR/unaligned_references_external_macro.rs:5:1
    |
 LL | / unaligned_references_external_crate::mac! {
+LL | |
 LL | |     #[repr(packed)]
 LL | |     pub struct X {
 LL | |         pub field: u16
 LL | |     }
 LL | | }
    | |_^
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/macros/issue-83340.rs b/src/test/ui/macros/issue-83340.rs
new file mode 100644
index 00000000000..d26200295cd
--- /dev/null
+++ b/src/test/ui/macros/issue-83340.rs
@@ -0,0 +1,8 @@
+// check-fail
+
+fn main() {
+    println!(
+        "\
+\n {} │", //~ ERROR: 1 positional argument in format string, but no arguments were given
+    );
+}
diff --git a/src/test/ui/macros/issue-83340.stderr b/src/test/ui/macros/issue-83340.stderr
new file mode 100644
index 00000000000..1935de02b57
--- /dev/null
+++ b/src/test/ui/macros/issue-83340.stderr
@@ -0,0 +1,8 @@
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/issue-83340.rs:6:4
+   |
+LL | \n {} │",
+   |    ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/issue-83344.rs b/src/test/ui/macros/issue-83344.rs
new file mode 100644
index 00000000000..c5f7f723587
--- /dev/null
+++ b/src/test/ui/macros/issue-83344.rs
@@ -0,0 +1,6 @@
+// check-fail
+
+fn main() {
+    println!("{}\
+"); //~^ ERROR: 1 positional argument in format string, but no arguments were given
+}
diff --git a/src/test/ui/macros/issue-83344.stderr b/src/test/ui/macros/issue-83344.stderr
new file mode 100644
index 00000000000..1ef70f87a1f
--- /dev/null
+++ b/src/test/ui/macros/issue-83344.stderr
@@ -0,0 +1,8 @@
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/issue-83344.rs:4:15
+   |
+LL |     println!("{}\
+   |               ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-or-patterns-back-compat.fixed b/src/test/ui/macros/macro-or-patterns-back-compat.fixed
new file mode 100644
index 00000000000..4e8b057457c
--- /dev/null
+++ b/src/test/ui/macros/macro-or-patterns-back-compat.fixed
@@ -0,0 +1,26 @@
+// ignore-tidy-linelength
+// run-rustfix
+
+#![feature(edition_macro_pats)]
+#![deny(or_patterns_back_compat)]
+#![allow(unused_macros)]
+macro_rules! foo { ($x:pat2015 | $y:pat) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+macro_rules! bar { ($($x:pat2015)+ | $($y:pat)+) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+macro_rules! baz { ($x:pat2015 | $y:pat2015) => {} } // should be ok
+macro_rules! qux { ($x:pat2015 | $y:pat) => {} } // should be ok
+macro_rules! ogg { ($x:pat2015 | $y:pat2015) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+macro_rules! match_any {
+    ( $expr:expr , $( $( $pat:pat2015 )|+ => $expr_arm:expr ),+ ) => { //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+        match $expr {
+            $(
+                $( $pat => $expr_arm, )+
+            )+
+        }
+    };
+}
+
+fn main() {
+    let result: Result<i64, i32> = Err(42);
+    let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into());
+    assert_eq!(int, 42);
+}
diff --git a/src/test/ui/macros/macro-or-patterns-back-compat.rs b/src/test/ui/macros/macro-or-patterns-back-compat.rs
new file mode 100644
index 00000000000..023abae36d0
--- /dev/null
+++ b/src/test/ui/macros/macro-or-patterns-back-compat.rs
@@ -0,0 +1,26 @@
+// ignore-tidy-linelength
+// run-rustfix
+
+#![feature(edition_macro_pats)]
+#![deny(or_patterns_back_compat)]
+#![allow(unused_macros)]
+macro_rules! foo { ($x:pat | $y:pat) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+macro_rules! baz { ($x:pat2015 | $y:pat2015) => {} } // should be ok
+macro_rules! qux { ($x:pat2015 | $y:pat) => {} } // should be ok
+macro_rules! ogg { ($x:pat | $y:pat2015) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+macro_rules! match_any {
+    ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+        match $expr {
+            $(
+                $( $pat => $expr_arm, )+
+            )+
+        }
+    };
+}
+
+fn main() {
+    let result: Result<i64, i32> = Err(42);
+    let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into());
+    assert_eq!(int, 42);
+}
diff --git a/src/test/ui/macros/macro-or-patterns-back-compat.stderr b/src/test/ui/macros/macro-or-patterns-back-compat.stderr
new file mode 100644
index 00000000000..29bbd696033
--- /dev/null
+++ b/src/test/ui/macros/macro-or-patterns-back-compat.stderr
@@ -0,0 +1,32 @@
+error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+  --> $DIR/macro-or-patterns-back-compat.rs:7:21
+   |
+LL | macro_rules! foo { ($x:pat | $y:pat) => {} }
+   |                     ^^^^^^ help: use pat2015 to preserve semantics: `$x:pat2015`
+   |
+note: the lint level is defined here
+  --> $DIR/macro-or-patterns-back-compat.rs:5:9
+   |
+LL | #![deny(or_patterns_back_compat)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+  --> $DIR/macro-or-patterns-back-compat.rs:8:23
+   |
+LL | macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} }
+   |                       ^^^^^^ help: use pat2015 to preserve semantics: `$x:pat2015`
+
+error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+  --> $DIR/macro-or-patterns-back-compat.rs:11:21
+   |
+LL | macro_rules! ogg { ($x:pat | $y:pat2015) => {} }
+   |                     ^^^^^^ help: use pat2015 to preserve semantics: `$x:pat2015`
+
+error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+  --> $DIR/macro-or-patterns-back-compat.rs:13:26
+   |
+LL |     ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
+   |                          ^^^^^^^^ help: use pat2015 to preserve semantics: `$pat:pat2015`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/mir/issue-83499-input-output-iteration-ice.rs b/src/test/ui/mir/issue-83499-input-output-iteration-ice.rs
new file mode 100644
index 00000000000..4d404d015ec
--- /dev/null
+++ b/src/test/ui/mir/issue-83499-input-output-iteration-ice.rs
@@ -0,0 +1,10 @@
+// Test that when in MIR the amount of local_decls and amount of normalized_input_tys don't match
+// that an out-of-bounds access does not occur.
+#![feature(c_variadic)]
+
+fn main() {}
+
+fn foo(_: Bar, ...) -> impl {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~| ERROR cannot find type `Bar` in this scope
+//~| ERROR at least one trait must be specified
diff --git a/src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr b/src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr
new file mode 100644
index 00000000000..eb172684899
--- /dev/null
+++ b/src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr
@@ -0,0 +1,21 @@
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/issue-83499-input-output-iteration-ice.rs:7:16
+   |
+LL | fn foo(_: Bar, ...) -> impl {}
+   |                ^^^
+
+error: at least one trait must be specified
+  --> $DIR/issue-83499-input-output-iteration-ice.rs:7:24
+   |
+LL | fn foo(_: Bar, ...) -> impl {}
+   |                        ^^^^
+
+error[E0412]: cannot find type `Bar` in this scope
+  --> $DIR/issue-83499-input-output-iteration-ice.rs:7:11
+   |
+LL | fn foo(_: Bar, ...) -> impl {}
+   |           ^^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs
index 0e3ea4bc8c9..6aa34354a7a 100644
--- a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs
+++ b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs
@@ -8,7 +8,7 @@ struct ChunkingIterator<T, S: 'static + Iterator<Item = T>> {
 impl<T, S: Iterator<Item = T>> Iterator for ChunkingIterator<T, S> {
     type Item = IteratorChunk<T, S>; //~ ERROR missing lifetime
 
-    fn next(&mut self) -> Option<IteratorChunk<T, S>> { //~ ERROR `impl`
+    fn next(&mut self) -> Option<IteratorChunk<T, S>> {
         todo!()
     }
 }
diff --git a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
index 5df35fa571c..1e035ff99d0 100644
--- a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
+++ b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
@@ -9,22 +9,6 @@ help: consider introducing a named lifetime parameter
 LL |     type Item<'a> = IteratorChunk<'a, T, S>;
    |              ^^^^                 ^^^
 
-error: `impl` item signature doesn't match `trait` item signature
-  --> $DIR/issue-74918-missing-lifetime.rs:11:5
-   |
-LL |     fn next(&mut self) -> Option<IteratorChunk<T, S>> {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'_, T, S>>`
-   | 
-  ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn next(&mut self) -> Option<Self::Item>;
-   |     ----------------------------------------- expected `fn(&mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, _, _>>`
-   |
-   = note: expected `fn(&mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, _, _>>`
-              found `fn(&mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'_, _, _>>`
-   = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
-   = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
index 4e122d930fc..ff16bf0e078 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -6,7 +6,7 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) i32)),
+               for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) i32)),
                (),
            ]
 
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr
index 44d1d2327fc..22398f08572 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr
@@ -6,7 +6,7 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32)),
+               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32)),
                (),
            ]
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
index fa9f994c4fa..11420efaa06 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -10,7 +10,7 @@ LL | |         },
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)),
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#4r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index 0555f79bcb0..98c3c28fb43 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -11,7 +11,7 @@ LL | |     });
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)),
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
index 0932f941548..30ef343b261 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -10,7 +10,7 @@ LL | |     })
    |
    = note: defining type: case1::{closure#0} with closure substs [
                i32,
-               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>)),
+               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>)),
                (),
            ]
 
@@ -49,7 +49,7 @@ LL | |     })
    |
    = note: defining type: case2::{closure#0} with closure substs [
                i32,
-               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>)),
+               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>)),
                (),
            ]
    = note: number of external vids: 2
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index bf6e2a922ed..29993b129c7 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -12,7 +12,7 @@ LL | |     });
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) u32>)),
+               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#2r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
index a3d993848cb..cb505d8b1ec 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -12,7 +12,7 @@ LL | |     });
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)),
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
index 60dca1baa40..2ec9d4d8db1 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -11,7 +11,7 @@ LL | |     });
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)),
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
index cbb10eb187e..21e4232c788 100644
--- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
@@ -10,7 +10,7 @@ LL | |         },
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)),
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
index f9f1d8bb6ff..8b9b0435420 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -11,7 +11,7 @@ LL | |     });
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)),
+               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#2r
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
index 1587c28e1be..060ce690f03 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -11,7 +11,7 @@ LL | |     });
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)),
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
index 44f743310b4..5fc1d5c4361 100644
--- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
+++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
@@ -6,7 +6,7 @@ LL |     expect_sig(|a, b| b); // ought to return `a`
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) i32,
+               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) i32,
                (),
            ]
 
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
index dbf76cd1329..baf223b786b 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -6,7 +6,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    |
    = note: defining type: generic::<T>::{closure#0} with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) T)),
+               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) T)),
                (),
            ]
    = note: number of external vids: 2
@@ -31,7 +31,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    |
    = note: defining type: generic_fail::<T>::{closure#0} with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) T)),
+               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) T)),
                (),
            ]
    = note: late-bound region is '_#2r
diff --git a/src/test/ui/non-copyable-void.stderr b/src/test/ui/non-copyable-void.stderr
index 8395a3a0563..99af04e7cd9 100644
--- a/src/test/ui/non-copyable-void.stderr
+++ b/src/test/ui/non-copyable-void.stderr
@@ -3,14 +3,6 @@ error[E0599]: no method named `clone` found for enum `c_void` in the current sco
    |
 LL |         let _z = (*y).clone();
    |                       ^^^^^ method not found in `c_void`
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<c_void>` here
-   |        the method is available for `Rc<c_void>` here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/noncopyable-class.stderr b/src/test/ui/noncopyable-class.stderr
index b8e467d8402..4674c16eb43 100644
--- a/src/test/ui/noncopyable-class.stderr
+++ b/src/test/ui/noncopyable-class.stderr
@@ -6,14 +6,6 @@ LL | struct Foo {
 ...
 LL |     let _y = x.clone();
    |                ^^^^^ method not found in `Foo`
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<Foo>` here
-   |        the method is available for `Rc<Foo>` here
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
diff --git a/src/test/ui/packed/packed-struct-address-of-element.rs b/src/test/ui/packed/packed-struct-address-of-element.rs
index 812d23fb580..fb3875e6804 100644
--- a/src/test/ui/packed/packed-struct-address-of-element.rs
+++ b/src/test/ui/packed/packed-struct-address-of-element.rs
@@ -1,6 +1,6 @@
 // run-pass
 #![allow(dead_code)]
-#![deny(safe_packed_borrows)]
+#![deny(unaligned_references)]
 #![feature(raw_ref_op)]
 // ignore-emscripten weird assertion?
 
diff --git a/src/test/ui/packed/packed-struct-borrow-element-64bit.rs b/src/test/ui/packed/packed-struct-borrow-element-64bit.rs
new file mode 100644
index 00000000000..ad932fdcd01
--- /dev/null
+++ b/src/test/ui/packed/packed-struct-borrow-element-64bit.rs
@@ -0,0 +1,17 @@
+// run-pass (note: this is spec-UB, but it works for now)
+// ignore-32bit (needs `usize` to be 8-aligned to reproduce all the errors below)
+#![allow(dead_code)]
+// ignore-emscripten weird assertion?
+
+#[repr(C, packed(4))]
+struct Foo4C {
+    bar: u8,
+    baz: usize
+}
+
+pub fn main() {
+    let foo = Foo4C { bar: 1, baz: 2 };
+    let brw = &foo.baz; //~WARN reference to packed field is unaligned
+    //~^ previously accepted
+    assert_eq!(*brw, 2);
+}
diff --git a/src/test/ui/packed/packed-struct-borrow-element-64bit.stderr b/src/test/ui/packed/packed-struct-borrow-element-64bit.stderr
new file mode 100644
index 00000000000..766d8a72c34
--- /dev/null
+++ b/src/test/ui/packed/packed-struct-borrow-element-64bit.stderr
@@ -0,0 +1,13 @@
+warning: reference to packed field is unaligned
+  --> $DIR/packed-struct-borrow-element-64bit.rs:14:15
+   |
+LL |     let brw = &foo.baz;
+   |               ^^^^^^^^
+   |
+   = note: `#[warn(unaligned_references)]` on by default
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/packed/packed-struct-borrow-element.rs b/src/test/ui/packed/packed-struct-borrow-element.rs
index 0072b6191eb..fb6c9c11d56 100644
--- a/src/test/ui/packed/packed-struct-borrow-element.rs
+++ b/src/test/ui/packed/packed-struct-borrow-element.rs
@@ -22,14 +22,12 @@ struct Foo4C {
 
 pub fn main() {
     let foo = Foo1 { bar: 1, baz: 2 };
-    let brw = unsafe { &foo.baz };
+    let brw = &foo.baz; //~WARN reference to packed field is unaligned
+    //~^ previously accepted
     assert_eq!(*brw, 2);
 
     let foo = Foo2 { bar: 1, baz: 2 };
-    let brw = unsafe { &foo.baz };
-    assert_eq!(*brw, 2);
-
-    let foo = Foo4C { bar: 1, baz: 2 };
-    let brw = unsafe { &foo.baz };
+    let brw = &foo.baz; //~WARN reference to packed field is unaligned
+    //~^ previously accepted
     assert_eq!(*brw, 2);
 }
diff --git a/src/test/ui/packed/packed-struct-borrow-element.stderr b/src/test/ui/packed/packed-struct-borrow-element.stderr
new file mode 100644
index 00000000000..5764e951a46
--- /dev/null
+++ b/src/test/ui/packed/packed-struct-borrow-element.stderr
@@ -0,0 +1,23 @@
+warning: reference to packed field is unaligned
+  --> $DIR/packed-struct-borrow-element.rs:25:15
+   |
+LL |     let brw = &foo.baz;
+   |               ^^^^^^^^
+   |
+   = note: `#[warn(unaligned_references)]` on by default
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+
+warning: reference to packed field is unaligned
+  --> $DIR/packed-struct-borrow-element.rs:30:15
+   |
+LL |     let brw = &foo.baz;
+   |               ^^^^^^^^
+   |
+   = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/proc-macro/auxiliary/issue-75801.rs b/src/test/ui/proc-macro/auxiliary/issue-75801.rs
new file mode 100644
index 00000000000..d6c031d7d4f
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/issue-75801.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn foo(_args: TokenStream, item: TokenStream) -> TokenStream {
+    item
+}
diff --git a/src/test/ui/proc-macro/auxiliary/issue-79825.rs b/src/test/ui/proc-macro/auxiliary/issue-79825.rs
new file mode 100644
index 00000000000..930891b1d43
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/issue-79825.rs
@@ -0,0 +1,14 @@
+// force-host
+// no-prefer-dynamic
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn assert_input(args: TokenStream, input: TokenStream) -> TokenStream {
+    assert_eq!(input.to_string(), "trait Alias = Sized ;");
+    assert!(args.is_empty());
+    TokenStream::new()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs b/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs
index 52ebe8e7fb2..27676a5cb81 100644
--- a/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs
+++ b/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs
@@ -2,14 +2,15 @@ pub struct FirstStruct;
 
 #[macro_export]
 macro_rules! outer_macro {
-    ($name:ident) => {
+    ($name:ident, $attr_struct_name:ident) => {
         #[macro_export]
         macro_rules! inner_macro {
-            ($wrapper:ident) => {
-                $wrapper!($name)
+            ($bang_macro:ident, $attr_macro:ident) => {
+                $bang_macro!($name);
+                #[$attr_macro] struct $attr_struct_name {}
             }
         }
     }
 }
 
-outer_macro!(FirstStruct);
+outer_macro!(FirstStruct, FirstAttrStruct);
diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr
index 9b946b5e244..5a4ed65ecdc 100644
--- a/src/test/ui/proc-macro/generate-mod.stderr
+++ b/src/test/ui/proc-macro/generate-mod.stderr
@@ -46,7 +46,8 @@ LL | #[derive(generate_mod::CheckDerive)]
    |
    = note: `#[warn(proc_macro_derive_resolution_fallback)]` on by default
    = 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 #50504 <https://github.com/rust-lang/rust/issues/50504>
+   = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+   = note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: cannot find type `OuterDerive` in this scope
   --> $DIR/generate-mod.rs:16:10
@@ -55,7 +56,8 @@ LL | #[derive(generate_mod::CheckDerive)]
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
    |
    = 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 #50504 <https://github.com/rust-lang/rust/issues/50504>
+   = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+   = note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: cannot find type `FromOutside` in this scope
   --> $DIR/generate-mod.rs:23:14
@@ -64,7 +66,8 @@ LL |     #[derive(generate_mod::CheckDerive)]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
    |
    = 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 #50504 <https://github.com/rust-lang/rust/issues/50504>
+   = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+   = note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: cannot find type `OuterDerive` in this scope
   --> $DIR/generate-mod.rs:23:14
@@ -73,7 +76,8 @@ LL |     #[derive(generate_mod::CheckDerive)]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
    |
    = 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 #50504 <https://github.com/rust-lang/rust/issues/50504>
+   = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+   = note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 4 previous errors; 4 warnings emitted
 
diff --git a/src/test/ui/proc-macro/inner-attrs.rs b/src/test/ui/proc-macro/inner-attrs.rs
index 6a353ca3263..5707621f80e 100644
--- a/src/test/ui/proc-macro/inner-attrs.rs
+++ b/src/test/ui/proc-macro/inner-attrs.rs
@@ -1,10 +1,10 @@
-// check-pass
 // compile-flags: -Z span-debug --error-format human
 // aux-build:test-macros.rs
 
 #![feature(custom_inner_attributes)]
 #![feature(proc_macro_hygiene)]
 #![feature(stmt_expr_attributes)]
+#![feature(rustc_attrs)]
 
 #![no_std] // Don't load unnecessary hygiene information from std
 extern crate std;
@@ -25,17 +25,34 @@ struct MyStruct {
 
 fn bar() {
     (#![print_target_and_args(fifth)] 1, 2);
+    //~^ ERROR expected non-macro inner attribute, found attribute macro
+
+    #[print_target_and_args(tuple_attrs)] (
+        #![cfg_attr(FALSE, rustc_dummy)]
+        3, 4, {
+            #![cfg_attr(not(FALSE), rustc_dummy(innermost))]
+            5
+        }
+    );
+
+    #[print_target_and_args(array_attrs)] [
+        #![rustc_dummy(inner)]
+        true; 0
+    ];
 
     [#![print_target_and_args(sixth)] 1 , 2];
+    //~^ ERROR expected non-macro inner attribute, found attribute macro
     [#![print_target_and_args(seventh)] true ; 5];
-
+    //~^ ERROR expected non-macro inner attribute, found attribute macro
 
     match 0 {
         #![print_target_and_args(eighth)]
+        //~^ ERROR expected non-macro inner attribute, found attribute macro
         _ => {}
     }
 
     MyStruct { #![print_target_and_args(ninth)] field: true };
+    //~^ ERROR expected non-macro inner attribute, found attribute macro
 }
 
 extern {
diff --git a/src/test/ui/proc-macro/inner-attrs.stderr b/src/test/ui/proc-macro/inner-attrs.stderr
new file mode 100644
index 00000000000..db774cbfb8f
--- /dev/null
+++ b/src/test/ui/proc-macro/inner-attrs.stderr
@@ -0,0 +1,32 @@
+error: expected non-macro inner attribute, found attribute macro `print_target_and_args`
+  --> $DIR/inner-attrs.rs:27:9
+   |
+LL |     (#![print_target_and_args(fifth)] 1, 2);
+   |         ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute
+
+error: expected non-macro inner attribute, found attribute macro `print_target_and_args`
+  --> $DIR/inner-attrs.rs:43:9
+   |
+LL |     [#![print_target_and_args(sixth)] 1 , 2];
+   |         ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute
+
+error: expected non-macro inner attribute, found attribute macro `print_target_and_args`
+  --> $DIR/inner-attrs.rs:45:9
+   |
+LL |     [#![print_target_and_args(seventh)] true ; 5];
+   |         ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute
+
+error: expected non-macro inner attribute, found attribute macro `print_target_and_args`
+  --> $DIR/inner-attrs.rs:49:12
+   |
+LL |         #![print_target_and_args(eighth)]
+   |            ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute
+
+error: expected non-macro inner attribute, found attribute macro `print_target_and_args`
+  --> $DIR/inner-attrs.rs:54:19
+   |
+LL |     MyStruct { #![print_target_and_args(ninth)] field: true };
+   |                   ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/proc-macro/inner-attrs.stdout b/src/test/ui/proc-macro/inner-attrs.stdout
index 2fd8d8a242e..ae04544e533 100644
--- a/src/test/ui/proc-macro/inner-attrs.stdout
+++ b/src/test/ui/proc-macro/inner-attrs.stdout
@@ -290,231 +290,251 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/inner-attrs.rs:17:1: 20:2 (#0),
     },
 ]
-PRINT-ATTR_ARGS INPUT (DISPLAY): fifth
+PRINT-ATTR_ARGS INPUT (DISPLAY): tuple_attrs
 PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
     Ident {
-        ident: "fifth",
-        span: $DIR/inner-attrs.rs:27:31: 27:36 (#0),
+        ident: "tuple_attrs",
+        span: $DIR/inner-attrs.rs:30:29: 30:40 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): (1, 2) ;
+PRINT-ATTR INPUT (DISPLAY): (# ! [cfg_attr(FALSE, rustc_dummy)] 3, 4,
+ { # ! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
-            Literal {
-                kind: Integer,
-                symbol: "1",
-                suffix: None,
-                span: $DIR/inner-attrs.rs:27:5: 27:45 (#0),
+            Punct {
+                ch: '#',
+                spacing: Joint,
+                span: $DIR/inner-attrs.rs:31:9: 31:10 (#0),
             },
             Punct {
-                ch: ',',
+                ch: '!',
                 spacing: Alone,
-                span: $DIR/inner-attrs.rs:27:5: 27:45 (#0),
+                span: $DIR/inner-attrs.rs:31:10: 31:11 (#0),
             },
-            Literal {
-                kind: Integer,
-                symbol: "2",
-                suffix: None,
-                span: $DIR/inner-attrs.rs:27:5: 27:45 (#0),
+            Group {
+                delimiter: Bracket,
+                stream: TokenStream [
+                    Ident {
+                        ident: "cfg_attr",
+                        span: $DIR/inner-attrs.rs:31:12: 31:20 (#0),
+                    },
+                    Group {
+                        delimiter: Parenthesis,
+                        stream: TokenStream [
+                            Ident {
+                                ident: "FALSE",
+                                span: $DIR/inner-attrs.rs:31:21: 31:26 (#0),
+                            },
+                            Punct {
+                                ch: ',',
+                                spacing: Alone,
+                                span: $DIR/inner-attrs.rs:31:26: 31:27 (#0),
+                            },
+                            Ident {
+                                ident: "rustc_dummy",
+                                span: $DIR/inner-attrs.rs:31:28: 31:39 (#0),
+                            },
+                        ],
+                        span: $DIR/inner-attrs.rs:31:20: 31:40 (#0),
+                    },
+                ],
+                span: $DIR/inner-attrs.rs:31:11: 31:41 (#0),
             },
-        ],
-        span: $DIR/inner-attrs.rs:27:5: 27:45 (#0),
-    },
-    Punct {
-        ch: ';',
-        spacing: Alone,
-        span: $DIR/inner-attrs.rs:27:5: 27:45 (#0),
-    },
-]
-PRINT-ATTR_ARGS INPUT (DISPLAY): sixth
-PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
-    Ident {
-        ident: "sixth",
-        span: $DIR/inner-attrs.rs:29:31: 29:36 (#0),
-    },
-]
-PRINT-ATTR INPUT (DISPLAY): [1, 2] ;
-PRINT-ATTR INPUT (DEBUG): TokenStream [
-    Group {
-        delimiter: Bracket,
-        stream: TokenStream [
             Literal {
                 kind: Integer,
-                symbol: "1",
+                symbol: "3",
                 suffix: None,
-                span: $DIR/inner-attrs.rs:29:5: 29:46 (#0),
+                span: $DIR/inner-attrs.rs:32:9: 32:10 (#0),
             },
             Punct {
                 ch: ',',
                 spacing: Alone,
-                span: $DIR/inner-attrs.rs:29:5: 29:46 (#0),
+                span: $DIR/inner-attrs.rs:32:10: 32:11 (#0),
             },
             Literal {
                 kind: Integer,
-                symbol: "2",
+                symbol: "4",
                 suffix: None,
-                span: $DIR/inner-attrs.rs:29:5: 29:46 (#0),
-            },
-        ],
-        span: $DIR/inner-attrs.rs:29:5: 29:46 (#0),
-    },
-    Punct {
-        ch: ';',
-        spacing: Alone,
-        span: $DIR/inner-attrs.rs:29:5: 29:46 (#0),
-    },
-]
-PRINT-ATTR_ARGS INPUT (DISPLAY): seventh
-PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
-    Ident {
-        ident: "seventh",
-        span: $DIR/inner-attrs.rs:30:31: 30:38 (#0),
-    },
-]
-PRINT-ATTR INPUT (DISPLAY): [true ; 5] ;
-PRINT-ATTR INPUT (DEBUG): TokenStream [
-    Group {
-        delimiter: Bracket,
-        stream: TokenStream [
-            Ident {
-                ident: "true",
-                span: $DIR/inner-attrs.rs:30:5: 30:51 (#0),
+                span: $DIR/inner-attrs.rs:32:12: 32:13 (#0),
             },
             Punct {
-                ch: ';',
+                ch: ',',
                 spacing: Alone,
-                span: $DIR/inner-attrs.rs:30:5: 30:51 (#0),
+                span: $DIR/inner-attrs.rs:32:13: 32:14 (#0),
             },
-            Literal {
-                kind: Integer,
-                symbol: "5",
-                suffix: None,
-                span: $DIR/inner-attrs.rs:30:5: 30:51 (#0),
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [
+                    Punct {
+                        ch: '#',
+                        spacing: Joint,
+                        span: $DIR/inner-attrs.rs:33:13: 33:14 (#0),
+                    },
+                    Punct {
+                        ch: '!',
+                        spacing: Alone,
+                        span: $DIR/inner-attrs.rs:33:14: 33:15 (#0),
+                    },
+                    Group {
+                        delimiter: Bracket,
+                        stream: TokenStream [
+                            Ident {
+                                ident: "cfg_attr",
+                                span: $DIR/inner-attrs.rs:33:16: 33:24 (#0),
+                            },
+                            Group {
+                                delimiter: Parenthesis,
+                                stream: TokenStream [
+                                    Ident {
+                                        ident: "not",
+                                        span: $DIR/inner-attrs.rs:33:25: 33:28 (#0),
+                                    },
+                                    Group {
+                                        delimiter: Parenthesis,
+                                        stream: TokenStream [
+                                            Ident {
+                                                ident: "FALSE",
+                                                span: $DIR/inner-attrs.rs:33:29: 33:34 (#0),
+                                            },
+                                        ],
+                                        span: $DIR/inner-attrs.rs:33:28: 33:35 (#0),
+                                    },
+                                    Punct {
+                                        ch: ',',
+                                        spacing: Alone,
+                                        span: $DIR/inner-attrs.rs:33:35: 33:36 (#0),
+                                    },
+                                    Ident {
+                                        ident: "rustc_dummy",
+                                        span: $DIR/inner-attrs.rs:33:37: 33:48 (#0),
+                                    },
+                                    Group {
+                                        delimiter: Parenthesis,
+                                        stream: TokenStream [
+                                            Ident {
+                                                ident: "innermost",
+                                                span: $DIR/inner-attrs.rs:33:49: 33:58 (#0),
+                                            },
+                                        ],
+                                        span: $DIR/inner-attrs.rs:33:48: 33:59 (#0),
+                                    },
+                                ],
+                                span: $DIR/inner-attrs.rs:33:24: 33:60 (#0),
+                            },
+                        ],
+                        span: $DIR/inner-attrs.rs:33:15: 33:61 (#0),
+                    },
+                    Literal {
+                        kind: Integer,
+                        symbol: "5",
+                        suffix: None,
+                        span: $DIR/inner-attrs.rs:34:13: 34:14 (#0),
+                    },
+                ],
+                span: $DIR/inner-attrs.rs:32:15: 35:10 (#0),
             },
         ],
-        span: $DIR/inner-attrs.rs:30:5: 30:51 (#0),
+        span: $DIR/inner-attrs.rs:30:43: 36:6 (#0),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: $DIR/inner-attrs.rs:30:5: 30:51 (#0),
+        span: $DIR/inner-attrs.rs:36:6: 36:7 (#0),
     },
 ]
-PRINT-ATTR_ARGS INPUT (DISPLAY): eighth
+PRINT-ATTR_ARGS INPUT (DISPLAY): array_attrs
 PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
     Ident {
-        ident: "eighth",
-        span: $DIR/inner-attrs.rs:34:34: 34:40 (#0),
+        ident: "array_attrs",
+        span: $DIR/inner-attrs.rs:38:29: 38:40 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): match 0 { _ => { } }
+PRINT-ATTR INPUT (DISPLAY): [# ! [rustc_dummy(inner)] true ; 0] ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
-    Ident {
-        ident: "match",
-        span: $DIR/inner-attrs.rs:33:5: 36:6 (#0),
-    },
-    Literal {
-        kind: Integer,
-        symbol: "0",
-        suffix: None,
-        span: $DIR/inner-attrs.rs:33:5: 36:6 (#0),
-    },
     Group {
-        delimiter: Brace,
+        delimiter: Bracket,
         stream: TokenStream [
-            Ident {
-                ident: "_",
-                span: $DIR/inner-attrs.rs:33:5: 36:6 (#0),
-            },
             Punct {
-                ch: '=',
+                ch: '#',
                 spacing: Joint,
-                span: $DIR/inner-attrs.rs:33:5: 36:6 (#0),
+                span: $DIR/inner-attrs.rs:38:43: 41:7 (#0),
             },
             Punct {
-                ch: '>',
+                ch: '!',
                 spacing: Alone,
-                span: $DIR/inner-attrs.rs:33:5: 36:6 (#0),
+                span: $DIR/inner-attrs.rs:38:43: 41:7 (#0),
             },
             Group {
-                delimiter: Brace,
-                stream: TokenStream [],
-                span: $DIR/inner-attrs.rs:33:5: 36:6 (#0),
-            },
-        ],
-        span: $DIR/inner-attrs.rs:33:5: 36:6 (#0),
-    },
-]
-PRINT-ATTR_ARGS INPUT (DISPLAY): ninth
-PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
-    Ident {
-        ident: "ninth",
-        span: $DIR/inner-attrs.rs:38:41: 38:46 (#0),
-    },
-]
-PRINT-ATTR INPUT (DISPLAY): MyStruct { field : true, } ;
-PRINT-ATTR INPUT (DEBUG): TokenStream [
-    Ident {
-        ident: "MyStruct",
-        span: $DIR/inner-attrs.rs:38:5: 38:63 (#0),
-    },
-    Group {
-        delimiter: Brace,
-        stream: TokenStream [
-            Ident {
-                ident: "field",
-                span: $DIR/inner-attrs.rs:38:5: 38:63 (#0),
-            },
-            Punct {
-                ch: ':',
-                spacing: Alone,
-                span: $DIR/inner-attrs.rs:38:5: 38:63 (#0),
+                delimiter: Bracket,
+                stream: TokenStream [
+                    Ident {
+                        ident: "rustc_dummy",
+                        span: $DIR/inner-attrs.rs:38:43: 41:7 (#0),
+                    },
+                    Group {
+                        delimiter: Parenthesis,
+                        stream: TokenStream [
+                            Ident {
+                                ident: "inner",
+                                span: $DIR/inner-attrs.rs:38:43: 41:7 (#0),
+                            },
+                        ],
+                        span: $DIR/inner-attrs.rs:38:43: 41:7 (#0),
+                    },
+                ],
+                span: $DIR/inner-attrs.rs:38:43: 41:7 (#0),
             },
             Ident {
                 ident: "true",
-                span: $DIR/inner-attrs.rs:38:5: 38:63 (#0),
+                span: $DIR/inner-attrs.rs:38:43: 41:7 (#0),
             },
             Punct {
-                ch: ',',
+                ch: ';',
                 spacing: Alone,
-                span: $DIR/inner-attrs.rs:38:5: 38:63 (#0),
+                span: $DIR/inner-attrs.rs:38:43: 41:7 (#0),
+            },
+            Literal {
+                kind: Integer,
+                symbol: "0",
+                suffix: None,
+                span: $DIR/inner-attrs.rs:38:43: 41:7 (#0),
             },
         ],
-        span: $DIR/inner-attrs.rs:38:5: 38:63 (#0),
+        span: $DIR/inner-attrs.rs:38:43: 41:7 (#0),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: $DIR/inner-attrs.rs:38:5: 38:63 (#0),
+        span: $DIR/inner-attrs.rs:38:43: 41:7 (#0),
     },
 ]
 PRINT-ATTR_ARGS INPUT (DISPLAY): tenth
 PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
     Ident {
         ident: "tenth",
-        span: $DIR/inner-attrs.rs:43:42: 43:47 (#0),
+        span: $DIR/inner-attrs.rs:60:42: 60:47 (#0),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): fn weird_extern() { }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "fn",
-        span: $DIR/inner-attrs.rs:42:5: 44:6 (#0),
+        span: $DIR/inner-attrs.rs:59:5: 61:6 (#0),
     },
     Ident {
         ident: "weird_extern",
-        span: $DIR/inner-attrs.rs:42:5: 44:6 (#0),
+        span: $DIR/inner-attrs.rs:59:5: 61:6 (#0),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [],
-        span: $DIR/inner-attrs.rs:42:5: 44:6 (#0),
+        span: $DIR/inner-attrs.rs:59:5: 61:6 (#0),
     },
     Group {
         delimiter: Brace,
         stream: TokenStream [],
-        span: $DIR/inner-attrs.rs:42:5: 44:6 (#0),
+        span: $DIR/inner-attrs.rs:59:5: 61:6 (#0),
     },
 ]
diff --git a/src/test/ui/proc-macro/issue-75801.rs b/src/test/ui/proc-macro/issue-75801.rs
new file mode 100644
index 00000000000..b07cde0fabd
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-75801.rs
@@ -0,0 +1,19 @@
+// aux-build: issue-75801.rs
+
+// Regression test for #75801.
+
+#[macro_use]
+extern crate issue_75801;
+
+macro_rules! foo {
+    ($arg:expr) => {
+        #[foo]
+        fn bar() {
+            let _bar: u32 = $arg;
+        }
+    };
+}
+
+foo!("baz"); //~ ERROR: mismatched types [E0308]
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-75801.stderr b/src/test/ui/proc-macro/issue-75801.stderr
new file mode 100644
index 00000000000..ee0a9bd7783
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-75801.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-75801.rs:17:6
+   |
+LL |             let _bar: u32 = $arg;
+   |                       --- expected due to this
+...
+LL | foo!("baz");
+   |      ^^^^^ expected `u32`, found `&str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/issue-79825.rs b/src/test/ui/proc-macro/issue-79825.rs
new file mode 100644
index 00000000000..f628469ce3a
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-79825.rs
@@ -0,0 +1,10 @@
+// check-pass
+// aux-build:issue-79825.rs
+#![feature(trait_alias)]
+
+extern crate issue_79825;
+
+#[issue_79825::assert_input]
+trait Alias = Sized;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-81555.rs b/src/test/ui/proc-macro/issue-81555.rs
new file mode 100644
index 00000000000..693f1f7dc39
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-81555.rs
@@ -0,0 +1,15 @@
+// check-pass
+// aux-build:test-macros.rs
+#![feature(stmt_expr_attributes, proc_macro_hygiene)]
+
+extern crate test_macros;
+
+use test_macros::identity_attr;
+
+#[identity_attr]
+fn main() {
+    let _x;
+    let y = ();
+    #[identity_attr]
+    _x = y;
+}
diff --git a/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs
new file mode 100644
index 00000000000..25adc5d2578
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs
@@ -0,0 +1,10 @@
+// Regression test for issue #83469
+// Ensures that we recover from `#[global_alloc]` on an invalid
+// stmt without an ICE
+
+fn outer() {
+    #[global_allocator]
+    fn inner() {} //~ ERROR allocators must be statics
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr
new file mode 100644
index 00000000000..ec0e3c4c754
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr
@@ -0,0 +1,8 @@
+error: allocators must be statics
+  --> $DIR/issue-83469-global-alloc-invalid-stmt.rs:7:5
+   |
+LL |     fn inner() {}
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/nested-macro-rules.rs b/src/test/ui/proc-macro/nested-macro-rules.rs
index 2fef0e5fad0..25ffcfad7c7 100644
--- a/src/test/ui/proc-macro/nested-macro-rules.rs
+++ b/src/test/ui/proc-macro/nested-macro-rules.rs
@@ -1,7 +1,7 @@
 // run-pass
 // aux-build:nested-macro-rules.rs
 // aux-build:test-macros.rs
-// compile-flags: -Z span-debug
+// compile-flags: -Z span-debug -Z macro-backtrace
 // edition:2018
 
 #![no_std] // Don't load unnecessary hygiene information from std
@@ -10,14 +10,14 @@ extern crate std;
 extern crate nested_macro_rules;
 extern crate test_macros;
 
-use test_macros::print_bang;
+use test_macros::{print_bang, print_attr};
 
 use nested_macro_rules::FirstStruct;
 struct SecondStruct;
 
 fn main() {
-    nested_macro_rules::inner_macro!(print_bang);
+    nested_macro_rules::inner_macro!(print_bang, print_attr);
 
-    nested_macro_rules::outer_macro!(SecondStruct);
-    inner_macro!(print_bang);
+    nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct);
+    inner_macro!(print_bang, print_attr);
 }
diff --git a/src/test/ui/proc-macro/nested-macro-rules.stdout b/src/test/ui/proc-macro/nested-macro-rules.stdout
index dcafe3b4bda..8292617fc16 100644
--- a/src/test/ui/proc-macro/nested-macro-rules.stdout
+++ b/src/test/ui/proc-macro/nested-macro-rules.stdout
@@ -5,10 +5,32 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         stream: TokenStream [
             Ident {
                 ident: "FirstStruct",
-                span: $DIR/auxiliary/nested-macro-rules.rs:15:14: 15:25 (#7),
+                span: $DIR/auxiliary/nested-macro-rules.rs:16:14: 16:25 (#7),
             },
         ],
-        span: $DIR/auxiliary/nested-macro-rules.rs:9:27: 9:32 (#6),
+        span: $DIR/auxiliary/nested-macro-rules.rs:9:30: 9:35 (#6),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): struct FirstAttrStruct { }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "struct",
+        span: $DIR/auxiliary/nested-macro-rules.rs:10:32: 10:38 (#6),
+    },
+    Group {
+        delimiter: None,
+        stream: TokenStream [
+            Ident {
+                ident: "FirstAttrStruct",
+                span: $DIR/auxiliary/nested-macro-rules.rs:16:27: 16:42 (#7),
+            },
+        ],
+        span: $DIR/auxiliary/nested-macro-rules.rs:10:39: 10:56 (#6),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [],
+        span: $DIR/auxiliary/nested-macro-rules.rs:10:57: 10:59 (#6),
     },
 ]
 PRINT-BANG INPUT (DISPLAY): SecondStruct
@@ -18,9 +40,31 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         stream: TokenStream [
             Ident {
                 ident: "SecondStruct",
-                span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#13),
+                span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#16),
             },
         ],
-        span: $DIR/auxiliary/nested-macro-rules.rs:9:27: 9:32 (#12),
+        span: $DIR/auxiliary/nested-macro-rules.rs:9:30: 9:35 (#15),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): struct SecondAttrStruct { }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "struct",
+        span: $DIR/auxiliary/nested-macro-rules.rs:10:32: 10:38 (#15),
+    },
+    Group {
+        delimiter: None,
+        stream: TokenStream [
+            Ident {
+                ident: "SecondAttrStruct",
+                span: $DIR/nested-macro-rules.rs:21:52: 21:68 (#16),
+            },
+        ],
+        span: $DIR/auxiliary/nested-macro-rules.rs:10:39: 10:56 (#15),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [],
+        span: $DIR/auxiliary/nested-macro-rules.rs:10:57: 10:59 (#15),
     },
 ]
diff --git a/src/test/ui/regions/regions-name-undeclared.stderr b/src/test/ui/regions/regions-name-undeclared.stderr
index ad0e7bd5afb..5f6ff280e65 100644
--- a/src/test/ui/regions/regions-name-undeclared.stderr
+++ b/src/test/ui/regions/regions-name-undeclared.stderr
@@ -1,3 +1,23 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-name-undeclared.rs:28:13
+   |
+LL |     enum E {
+   |           - help: consider introducing lifetime `'a` here: `<'a>`
+LL |         E1(&'a isize)
+   |             ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-name-undeclared.rs:31:13
+   |
+LL |     struct S {
+   |             - help: consider introducing lifetime `'a` here: `<'a>`
+LL |         f: &'a isize
+   |             ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/regions-name-undeclared.rs:16:24
    |
@@ -57,26 +77,6 @@ LL |     type X = Option<&'a isize>;
    = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
 
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/regions-name-undeclared.rs:28:13
-   |
-LL |     enum E {
-   |           - help: consider introducing lifetime `'a` here: `<'a>`
-LL |         E1(&'a isize)
-   |             ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-
-error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/regions-name-undeclared.rs:31:13
-   |
-LL |     struct S {
-   |             - help: consider introducing lifetime `'a` here: `<'a>`
-LL |         f: &'a isize
-   |             ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-
-error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-name-undeclared.rs:33:14
    |
 LL |     fn f(a: &'a isize) { }
diff --git a/src/test/ui/resolve/issue-82865.rs b/src/test/ui/resolve/issue-82865.rs
new file mode 100644
index 00000000000..07d88c413bf
--- /dev/null
+++ b/src/test/ui/resolve/issue-82865.rs
@@ -0,0 +1,13 @@
+// Regression test for #82865.
+
+#![feature(decl_macro)]
+
+use x::y::z; //~ ERROR: failed to resolve: maybe a missing crate `x`?
+
+macro mac () {
+    Box::z //~ ERROR: no function or associated item
+}
+
+fn main() {
+    mac!();
+}
diff --git a/src/test/ui/resolve/issue-82865.stderr b/src/test/ui/resolve/issue-82865.stderr
new file mode 100644
index 00000000000..027d7a0e0e4
--- /dev/null
+++ b/src/test/ui/resolve/issue-82865.stderr
@@ -0,0 +1,21 @@
+error[E0433]: failed to resolve: maybe a missing crate `x`?
+  --> $DIR/issue-82865.rs:5:5
+   |
+LL | use x::y::z;
+   |     ^ maybe a missing crate `x`?
+
+error[E0599]: no function or associated item named `z` found for struct `Box<_, _>` in the current scope
+  --> $DIR/issue-82865.rs:8:10
+   |
+LL |     Box::z
+   |          ^ function or associated item not found in `Box<_, _>`
+...
+LL |     mac!();
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0433, E0599.
+For more information about an error, try `rustc --explain E0433`.
diff --git a/src/test/ui/rustdoc/check-doc-alias-attr.stderr b/src/test/ui/rustdoc/check-doc-alias-attr.stderr
index f99d69dc101..250568be333 100644
--- a/src/test/ui/rustdoc/check-doc-alias-attr.stderr
+++ b/src/test/ui/rustdoc/check-doc-alias-attr.stderr
@@ -10,7 +10,7 @@ error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of s
 LL | #[doc(alias = 0)]
    |       ^^^^^^^^^
 
-error: '\"' character isn't allowed in `#[doc(alias = "...")]`
+error: '"' character isn't allowed in `#[doc(alias = "...")]`
   --> $DIR/check-doc-alias-attr.rs:9:15
    |
 LL | #[doc(alias = "\"")]
@@ -60,7 +60,7 @@ error: `#[doc(alias("a"))]` expects string literals
 LL | #[doc(alias(0))]
    |             ^
 
-error: '\"' character isn't allowed in `#[doc(alias("..."))]`
+error: '"' character isn't allowed in `#[doc(alias("..."))]`
   --> $DIR/check-doc-alias-attr.rs:20:13
    |
 LL | #[doc(alias("\""))]
diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
index 2954a499c18..b804ddfb024 100644
--- a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
+++ b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
@@ -9,6 +9,11 @@ LL |     fn foo(self: Box<Self>) {}
 ...
 LL |     A.foo();
    |       ^^^ method not found in `A`
+   |
+help: consider wrapping the receiver expression with the appropriate type
+   |
+LL |     Box::new(A).foo();
+   |     ^^^^^^^^^ ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr
index 89fe84c0d2d..e1ed0e42f98 100644
--- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr
+++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr
@@ -10,6 +10,11 @@ LL | struct A;
 ...
 LL |     A.foo()
    |       ^^^ method not found in `A`
+   |
+help: consider wrapping the receiver expression with the appropriate type
+   |
+LL |     Box::new(A).foo()
+   |     ^^^^^^^^^ ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/simd/simd-intrinsic-generic-reduction.rs b/src/test/ui/simd/simd-intrinsic-generic-reduction.rs
index 8b5afeac0bc..7193fb3527f 100644
--- a/src/test/ui/simd/simd-intrinsic-generic-reduction.rs
+++ b/src/test/ui/simd/simd-intrinsic-generic-reduction.rs
@@ -2,7 +2,6 @@
 #![allow(non_camel_case_types)]
 
 // ignore-emscripten
-// min-system-llvm-version: 9.0
 
 // Test that the simd_reduce_{op} intrinsics produce the correct results.
 
diff --git a/src/test/ui/specialization/issue-68830-spurious-diagnostics.rs b/src/test/ui/specialization/issue-68830-spurious-diagnostics.rs
new file mode 100644
index 00000000000..d11ec798332
--- /dev/null
+++ b/src/test/ui/specialization/issue-68830-spurious-diagnostics.rs
@@ -0,0 +1,23 @@
+// A regression test for #68830. This checks we don't emit
+// a verbose `conflicting implementations` error.
+
+#![feature(specialization)]
+#![allow(incomplete_features)]
+
+struct BadStruct {
+    err: MissingType //~ ERROR: cannot find type `MissingType` in this scope
+}
+
+trait MyTrait<T> {
+    fn foo();
+}
+
+impl<T, D> MyTrait<T> for D {
+    default fn foo() {}
+}
+
+impl<T> MyTrait<T> for BadStruct {
+    fn foo() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/issue-68830-spurious-diagnostics.stderr b/src/test/ui/specialization/issue-68830-spurious-diagnostics.stderr
new file mode 100644
index 00000000000..833f61dca8c
--- /dev/null
+++ b/src/test/ui/specialization/issue-68830-spurious-diagnostics.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `MissingType` in this scope
+  --> $DIR/issue-68830-spurious-diagnostics.rs:8:10
+   |
+LL |     err: MissingType
+   |          ^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
index 92208231b17..fa59d7a0313 100644
--- a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
+++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
@@ -1,4 +1,4 @@
-error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,)))`
+error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,)), [])`
   --> $DIR/repeated_projection_type.rs:19:1
    |
 LL | / impl<I, V: Id<This = (I,)>> X for V {
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 32961b7f87b..3786457fb1a 100644
--- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
+++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
@@ -46,6 +46,7 @@ error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
 LL |     Pin::new(x)
    |     ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send`
    |
+   = note: consider using `Box::pin`
    = note: required by `Pin::<P>::new`
 
 error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
@@ -54,6 +55,7 @@ error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
 LL |     Pin::new(Box::new(x))
    |     ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send`
    |
+   = note: consider using `Box::pin`
    = note: required by `Pin::<P>::new`
 
 error[E0308]: mismatched types
diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr
index 2854b830ba8..26efd50bb8f 100644
--- a/src/test/ui/suggestions/into-str.stderr
+++ b/src/test/ui/suggestions/into-str.stderr
@@ -7,6 +7,7 @@ LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {}
 LL |     foo(String::new());
    |     ^^^ the trait `From<String>` is not implemented for `&str`
    |
+   = note: to coerce a `String` into a `&str`, use `&*` as a prefix
    = note: required because of the requirements on the impl of `Into<&str>` for `String`
 
 error: aborting due to previous error
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr
deleted file mode 100644
index b509610b89e..00000000000
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr
+++ /dev/null
@@ -1,92 +0,0 @@
-error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/missing-lifetimes-in-signature.rs:37:11
-   |
-LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |        -  ^^ undeclared lifetime
-   |        |
-   |        help: consider introducing lifetime `'a` here: `'a,`
-
-error: lifetime may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:15:37
-   |
-LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
-   |                          -          ^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
-   |                          |
-   |                          let's call the lifetime of this reference `'1`
-   |
-help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
-   |
-LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                     ^^^^^^^^^^^^^^^^^^
-
-error[E0311]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:25:37
-   |
-LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                     ^^^^^^^^^^^^^^^^^^
-   |
-note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 25:26...
-  --> $DIR/missing-lifetimes-in-signature.rs:25:26
-   |
-LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                          ^^^^^^
-
-error[E0311]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:47:45
-   |
-LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                             ^^^^^^^^^^^^^^^^^^
-   |
-note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 47:34...
-  --> $DIR/missing-lifetimes-in-signature.rs:47:34
-   |
-LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                  ^^^^^^
-
-error[E0311]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:59:58
-   |
-LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-   |                                                          ^^^^^^^^^^^^^^^^^^
-   |
-note: the parameter type `G` must be valid for the anonymous lifetime defined on the method body at 59:47...
-  --> $DIR/missing-lifetimes-in-signature.rs:59:47
-   |
-LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-   |                                               ^^^^^^
-
-error[E0311]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:68:45
-   |
-LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-   |                                             ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 68:34...
-  --> $DIR/missing-lifetimes-in-signature.rs:68:34
-   |
-LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-   |                                  ^^^^^^
-
-error[E0621]: explicit lifetime required in the type of `dest`
-  --> $DIR/missing-lifetimes-in-signature.rs:73:5
-   |
-LL |   fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-   |                                    ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
-...
-LL | /     move || {
-LL | |         *dest = g.get();
-LL | |     }
-   | |_____^ lifetime `'a` required
-
-error[E0309]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:79:44
-   |
-LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
-   |                                            ^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `G: 'a`...
-
-error: aborting due to 8 previous errors
-
-Some errors have detailed explanations: E0261, E0309, E0621.
-For more information about an error, try `rustc --explain E0261`.
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
index 94dd826a15c..dd434ea5318 100644
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
@@ -16,14 +16,13 @@ fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
 where
     G: Get<T>
 {
-    move || { //~ ERROR `dest`
+    move || {
         *dest = g.get();
     }
 }
 
 // After applying suggestion for `foo`:
 fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-//~^ ERROR the parameter type `G` may not live long enough
 where
     G: Get<T>
 {
@@ -45,7 +44,6 @@ where
 
 // After applying suggestion for `baz`:
 fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-//~^ ERROR the parameter type `G` may not live long enough
 where
     G: Get<T>
 {
@@ -57,7 +55,6 @@ where
 // Same as above, but show that we pay attention to lifetime names from parent item
 impl<'a> Foo {
     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-        //~^ ERROR the parameter type `G` may not live long enough
         move || {
             *dest = g.get();
         }
@@ -66,7 +63,6 @@ impl<'a> Foo {
 
 // After applying suggestion for `qux`:
 fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-//~^ ERROR explicit lifetime required in the type of `dest`
 where
     G: Get<T>
 {
@@ -77,7 +73,6 @@ where
 
 // Potential incorrect attempt:
 fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
-//~^ ERROR the parameter type `G` may not live long enough
 where
     G: Get<T>
 {
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
index 789fff7acc2..916a6c2bf12 100644
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
@@ -1,112 +1,11 @@
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/missing-lifetimes-in-signature.rs:37:11
+  --> $DIR/missing-lifetimes-in-signature.rs:36:11
    |
 LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
    |        -  ^^ undeclared lifetime
    |        |
    |        help: consider introducing lifetime `'a` here: `'a,`
 
-error[E0759]: `dest` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
-  --> $DIR/missing-lifetimes-in-signature.rs:19:5
-   |
-LL |   fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
-   |                            ------ this data with an anonymous lifetime `'_`...
-...
-LL | /     move || {
-LL | |         *dest = g.get();
-LL | |     }
-   | |_____^ ...is captured here...
-   |
-note: ...and is required to live as long as `'static` here
-  --> $DIR/missing-lifetimes-in-signature.rs:15:37
-   |
-LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
-   |                                     ^^^^^^^^^^^^^
-help: to declare that the `impl Trait` captures data from argument `dest`, you can add an explicit `'_` lifetime bound
-   |
-LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                                   ^^^^
-
-error[E0311]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:25:37
-   |
-LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                     ^^^^^^^^^^^^^^^^^^
-   |
-note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 25:26...
-  --> $DIR/missing-lifetimes-in-signature.rs:25:26
-   |
-LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                          ^^^^^^
-note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:30:5: 32:6]` will meet its required lifetime bounds
-  --> $DIR/missing-lifetimes-in-signature.rs:25:37
-   |
-LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                     ^^^^^^^^^^^^^^^^^^
-help: consider introducing an explicit lifetime bound
-   |
-LL | fn bar<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-   |        ^^^^^                                                   ^^^^
-
-error[E0311]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:47:45
-   |
-LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                             ^^^^^^^^^^^^^^^^^^
-   |
-note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 47:34...
-  --> $DIR/missing-lifetimes-in-signature.rs:47:34
-   |
-LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                  ^^^^^^
-note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:52:5: 54:6]` will meet its required lifetime bounds
-  --> $DIR/missing-lifetimes-in-signature.rs:47:45
-   |
-LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                             ^^^^^^^^^^^^^^^^^^
-help: consider introducing an explicit lifetime bound
-   |
-LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b
-   |        ^^^     ^^^^^^^                                                  ^^^^
-
-error[E0311]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:59:58
-   |
-LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-   |                                                          ^^^^^^^^^^^^^^^^^^
-   |
-note: the parameter type `G` must be valid for the anonymous lifetime defined on the method body at 59:47...
-  --> $DIR/missing-lifetimes-in-signature.rs:59:47
-   |
-LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-   |                                               ^^^^^^
-note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:61:9: 63:10]` will meet its required lifetime bounds
-  --> $DIR/missing-lifetimes-in-signature.rs:59:58
-   |
-LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-   |                                                          ^^^^^^^^^^^^^^^^^^
-help: consider introducing an explicit lifetime bound
-   |
-LL |     fn qux<'c, 'b, G: 'c + Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'c {
-   |            ^^^     ^^^^^^^                                                           ^^^^
-
-error[E0621]: explicit lifetime required in the type of `dest`
-  --> $DIR/missing-lifetimes-in-signature.rs:68:45
-   |
-LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-   |                                  ------     ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
-   |                                  |
-   |                                  help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
-
-error[E0309]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:79:44
-   |
-LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
-   |            -                               ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:84:5: 86:6]` will meet its required lifetime bounds
-   |            |
-   |            help: consider adding an explicit lifetime bound...: `G: 'a`
-
-error: aborting due to 7 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0261, E0309, E0621, E0759.
-For more information about an error, try `rustc --explain E0261`.
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr
index e6cec5cbd45..489926ea78a 100644
--- a/src/test/ui/suggestions/missing-lifetime-specifier.stderr
+++ b/src/test/ui/suggestions/missing-lifetime-specifier.stderr
@@ -142,30 +142,6 @@ help: consider using the `'static` lifetime
 LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                                 ^^^^^^^^^^^^^^^^^
 
-error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-specifier.rs:50:44
-   |
-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^ expected named lifetime parameter
-   |
-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-help: consider using the `'static` lifetime
-   |
-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^^^^^^^^
-
-error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-specifier.rs:50:44
-   |
-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^ expected named lifetime parameter
-   |
-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-help: consider using the `'static` lifetime
-   |
-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^^^^^^^^
-
 error[E0107]: this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:43:44
    |
@@ -256,6 +232,18 @@ help: add missing lifetime argument
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
    |                                                        ^^^^
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing-lifetime-specifier.rs:50:44
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                            ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                            ^^^^^^^^
+
 error[E0107]: this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:50:45
    |
@@ -274,6 +262,18 @@ help: add missing lifetime argument
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
    |                                                        ^^^^
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing-lifetime-specifier.rs:50:44
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                            ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                            ^^^^^^^^
+
 error[E0107]: this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:50:45
    |
diff --git a/src/test/ui/suggestions/path-display.stderr b/src/test/ui/suggestions/path-display.stderr
index b08e22eaab7..3ee2860b4ff 100644
--- a/src/test/ui/suggestions/path-display.stderr
+++ b/src/test/ui/suggestions/path-display.stderr
@@ -2,10 +2,10 @@ error[E0277]: `Path` doesn't implement `std::fmt::Display`
   --> $DIR/path-display.rs:5:20
    |
 LL |     println!("{}", path);
-   |                    ^^^^ `Path` cannot be formatted with the default formatter
+   |                    ^^^^ `Path` cannot be formatted with the default formatter; call `.display()` on it
    |
    = help: the trait `std::fmt::Display` is not implemented for `Path`
-   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data
    = note: required because of the requirements on the impl of `std::fmt::Display` for `&Path`
    = note: required by `std::fmt::Display::fmt`
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/ui/symbol-names/basic.legacy.stderr b/src/test/ui/symbol-names/basic.legacy.stderr
index 7155d88be96..3dd2b19fbf9 100644
--- a/src/test/ui/symbol-names/basic.legacy.stderr
+++ b/src/test/ui/symbol-names/basic.legacy.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_ZN5basic4main17hfcf1daab33c43a6aE)
+error: symbol-name(_ZN5basic4main17h6c535bbea2051f85E)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(basic::main::hfcf1daab33c43a6a)
+error: demangling(basic::main::h6c535bbea2051f85)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr
index 9575875f5a8..65cc62b4d1d 100644
--- a/src/test/ui/symbol-names/issue-60925.legacy.stderr
+++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hb8ca3eb2682b1b51E)
+error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h6244e5288326926aE)
   --> $DIR/issue-60925.rs:22:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::hb8ca3eb2682b1b51)
+error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h6244e5288326926a)
   --> $DIR/issue-60925.rs:22:9
    |
 LL |         #[rustc_symbol_name]
diff --git a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr
index d39daaba206..01e36a4a62a 100644
--- a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr
+++ b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr
@@ -6,14 +6,6 @@ LL | struct Qux;
 ...
 LL |     Qux.clone();
    |         ^^^^^ method not found in `Qux`
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<Qux>` here
-   |        the method is available for `Rc<Qux>` here
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the trait `Clone` defines an item `clone`, but is explicitely unimplemented
diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.full_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.full_tait.stderr
index f544f61df97..53a0016c08e 100644
--- a/src/test/ui/type-alias-impl-trait/issue-63279.full_tait.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-63279.full_tait.stderr
@@ -11,10 +11,10 @@ error[E0271]: type mismatch resolving `<[closure@$DIR/issue-63279.rs:11:5: 11:28
   --> $DIR/issue-63279.rs:8:16
    |
 LL | type Closure = impl FnOnce();
-   |                ^^^^^^^^^^^^^ expected opaque type, found `()`
+   |                ^^^^^^^^^^^^^ expected `()`, found opaque type
    |
-   = note: expected opaque type `impl FnOnce<()>`
-                found unit type `()`
+   = note: expected unit type `()`
+            found opaque type `impl FnOnce<()>`
 
 error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.min_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.min_tait.stderr
index bdf414d0bad..be386ab90ea 100644
--- a/src/test/ui/type-alias-impl-trait/issue-63279.min_tait.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-63279.min_tait.stderr
@@ -11,10 +11,10 @@ error[E0271]: type mismatch resolving `<[closure@$DIR/issue-63279.rs:11:5: 11:28
   --> $DIR/issue-63279.rs:8:16
    |
 LL | type Closure = impl FnOnce();
-   |                ^^^^^^^^^^^^^ expected opaque type, found `()`
+   |                ^^^^^^^^^^^^^ expected `()`, found opaque type
    |
-   = note: expected opaque type `impl FnOnce<()>`
-                found unit type `()`
+   = note: expected unit type `()`
+            found opaque type `impl FnOnce<()>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr
index a793bf58d23..546394664df 100644
--- a/src/test/ui/union/union-derive-clone.stderr
+++ b/src/test/ui/union/union-derive-clone.stderr
@@ -25,14 +25,6 @@ LL | struct CloneNoCopy;
 ...
 LL |     let w = u.clone();
    |               ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<U5<CloneNoCopy>>` here
-   |        the method is available for `Rc<U5<CloneNoCopy>>` here
    |
    = note: the following trait bounds were not satisfied:
            `CloneNoCopy: Copy`
diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr
index 4bbacfc0a8b..6a355dd2562 100644
--- a/src/test/ui/unique-object-noncopyable.stderr
+++ b/src/test/ui/unique-object-noncopyable.stderr
@@ -10,14 +10,6 @@ LL |   trait Foo {
 LL |       let _z = y.clone();
    |                  ^^^^^ method cannot be called on `Box<dyn Foo>` due to unsatisfied trait bounds
    | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |       fn clone(&self) -> Self;
-   |          -----
-   |          |
-   |          the method is available for `Arc<Box<dyn Foo>>` here
-   |          the method is available for `Rc<Box<dyn Foo>>` here
-   | 
   ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
    |
 LL | / pub struct Box<
diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr
index dd0b7fc5489..a4421bcf809 100644
--- a/src/test/ui/unique-pinned-nocopy.stderr
+++ b/src/test/ui/unique-pinned-nocopy.stderr
@@ -7,14 +7,6 @@ LL |   struct R {
 LL |       let _j = i.clone();
    |                  ^^^^^ method cannot be called on `Box<R>` due to unsatisfied trait bounds
    | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |       fn clone(&self) -> Self;
-   |          -----
-   |          |
-   |          the method is available for `Arc<Box<R>>` here
-   |          the method is available for `Rc<Box<R>>` here
-   | 
   ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
    |
 LL | / pub struct Box<
diff --git a/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs b/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs
deleted file mode 100644
index 540612a7dce..00000000000
--- a/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-#![feature(unsafe_block_in_unsafe_fn)]
-
-#[repr(packed)]
-pub struct Packed {
-    data: &'static u32,
-}
-
-const PACKED: Packed = Packed { data: &0 };
-
-#[allow(safe_packed_borrows)]
-#[allow(unsafe_op_in_unsafe_fn)]
-unsafe fn allow_allow() {
-    &PACKED.data; // allowed
-}
-
-#[allow(safe_packed_borrows)]
-#[warn(unsafe_op_in_unsafe_fn)]
-unsafe fn allow_warn() {
-    &PACKED.data; // allowed
-}
-
-#[allow(safe_packed_borrows)]
-#[deny(unsafe_op_in_unsafe_fn)]
-unsafe fn allow_deny() {
-    &PACKED.data; // allowed
-}
-
-#[warn(safe_packed_borrows)]
-#[allow(unsafe_op_in_unsafe_fn)]
-unsafe fn warn_allow() {
-    &PACKED.data; // allowed
-}
-
-#[warn(safe_packed_borrows)]
-#[warn(unsafe_op_in_unsafe_fn)]
-unsafe fn warn_warn() {
-    &PACKED.data; //~ WARN
-    //~| WARNING this was previously accepted by the compiler but is being phased out
-}
-
-#[warn(safe_packed_borrows)]
-#[deny(unsafe_op_in_unsafe_fn)]
-unsafe fn warn_deny() {
-    &PACKED.data; //~ WARN
-    //~| WARNING this was previously accepted by the compiler but is being phased out
-}
-
-#[deny(safe_packed_borrows)]
-#[allow(unsafe_op_in_unsafe_fn)]
-unsafe fn deny_allow() {
-    &PACKED.data; // allowed
-}
-
-#[deny(safe_packed_borrows)]
-#[warn(unsafe_op_in_unsafe_fn)]
-unsafe fn deny_warn() {
-    &PACKED.data; //~ WARN
-}
-
-#[deny(safe_packed_borrows)]
-#[deny(unsafe_op_in_unsafe_fn)]
-unsafe fn deny_deny() {
-    &PACKED.data; //~ ERROR
-    //~| WARNING this was previously accepted by the compiler but is being phased out
-}
-
-fn main() {}
diff --git a/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr b/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr
deleted file mode 100644
index fda15159643..00000000000
--- a/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr
+++ /dev/null
@@ -1,60 +0,0 @@
-warning: borrow of packed field is unsafe and requires unsafe block (error E0133)
-  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:37:5
-   |
-LL |     &PACKED.data;
-   |     ^^^^^^^^^^^^ borrow of packed field
-   |
-note: the lint level is defined here
-  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:34:8
-   |
-LL | #[warn(safe_packed_borrows)]
-   |        ^^^^^^^^^^^^^^^^^^^
-   = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
-   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
-
-warning: borrow of packed field is unsafe and requires unsafe block (error E0133)
-  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:44:5
-   |
-LL |     &PACKED.data;
-   |     ^^^^^^^^^^^^ borrow of packed field
-   |
-note: the lint level is defined here
-  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:41:8
-   |
-LL | #[warn(safe_packed_borrows)]
-   |        ^^^^^^^^^^^^^^^^^^^
-   = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
-   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
-
-warning: borrow of packed field is unsafe and requires unsafe block (error E0133)
-  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:57:5
-   |
-LL |     &PACKED.data;
-   |     ^^^^^^^^^^^^ borrow of packed field
-   |
-note: the lint level is defined here
-  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:55:8
-   |
-LL | #[warn(unsafe_op_in_unsafe_fn)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^
-   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
-
-error: borrow of packed field is unsafe and requires unsafe block (error E0133)
-  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:63:5
-   |
-LL |     &PACKED.data;
-   |     ^^^^^^^^^^^^ borrow of packed field
-   |
-note: the lint level is defined here
-  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:60:8
-   |
-LL | #[deny(safe_packed_borrows)]
-   |        ^^^^^^^^^^^^^^^^^^^
-   = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
-   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
-
-error: aborting due to previous error; 3 warnings emitted
-
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 90691f2bfe9a50291a98983b1ed2feab51d5ca5
+Subproject 3c44c3c4b7900b8b13c85ead25ccaa8abb7d898
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 41c334c6816..f7916511edf 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -2103,6 +2103,7 @@ Released 2018-09-13
 [`if_let_some_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_some_result
 [`if_not_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_not_else
 [`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
+[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
 [`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
 [`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
 [`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
diff --git a/src/tools/clippy/CONTRIBUTING.md b/src/tools/clippy/CONTRIBUTING.md
index 5954ab25d19..e0a4d4455e9 100644
--- a/src/tools/clippy/CONTRIBUTING.md
+++ b/src/tools/clippy/CONTRIBUTING.md
@@ -18,11 +18,13 @@ All contributors are expected to follow the [Rust Code of Conduct].
     - [Finding something to fix/improve](#finding-something-to-fiximprove)
   - [Writing code](#writing-code)
   - [Getting code-completion for rustc internals to work](#getting-code-completion-for-rustc-internals-to-work)
+    - [IntelliJ Rust](#intellij-rust)
+    - [Rust Analyzer](#rust-analyzer)
   - [How Clippy works](#how-clippy-works)
-  - [Syncing changes between Clippy and `rust-lang/rust`](#syncing-changes-between-clippy-and-rust-langrust)
+  - [Syncing changes between Clippy and [`rust-lang/rust`]](#syncing-changes-between-clippy-and-rust-langrust)
     - [Patching git-subtree to work with big repos](#patching-git-subtree-to-work-with-big-repos)
-    - [Performing the sync from `rust-lang/rust` to Clippy](#performing-the-sync-from-rust-langrust-to-clippy)
-    - [Performing the sync from Clippy to `rust-lang/rust`](#performing-the-sync-from-clippy-to-rust-langrust)
+    - [Performing the sync from [`rust-lang/rust`] to Clippy](#performing-the-sync-from-rust-langrust-to-clippy)
+    - [Performing the sync from Clippy to [`rust-lang/rust`]](#performing-the-sync-from-clippy-to-rust-langrust)
     - [Defining remotes](#defining-remotes)
   - [Issue and PR triage](#issue-and-pr-triage)
   - [Bors and Homu](#bors-and-homu)
@@ -105,21 +107,41 @@ quick read.
 
 ## Getting code-completion for rustc internals to work
 
-Unfortunately, [`rust-analyzer`][ra_homepage] does not (yet?) understand how Clippy uses compiler-internals
+### IntelliJ Rust
+Unfortunately, [`IntelliJ Rust`][IntelliJ_rust_homepage] does not (yet?) understand how Clippy uses compiler-internals
 using `extern crate` and it also needs to be able to read the source files of the rustc-compiler which are not
 available via a `rustup` component at the time of writing.
 To work around this, you need to have a copy of the [rustc-repo][rustc_repo] available which can be obtained via
 `git clone https://github.com/rust-lang/rust/`.
 Then you can run a `cargo dev` command to automatically make Clippy use the rustc-repo via path-dependencies
-which rust-analyzer will be able to understand.
-Run `cargo dev ra_setup --repo-path <repo-path>` where `<repo-path>` is an absolute path to the rustc repo
+which `IntelliJ Rust` will be able to understand.
+Run `cargo dev ide_setup --repo-path <repo-path>` where `<repo-path>` is a path to the rustc repo
 you just cloned.
 The command will add path-dependencies pointing towards rustc-crates inside the rustc repo to
 Clippys `Cargo.toml`s and should allow rust-analyzer to understand most of the types that Clippy uses.
 Just make sure to remove the dependencies again before finally making a pull request!
 
-[ra_homepage]: https://rust-analyzer.github.io/
 [rustc_repo]: https://github.com/rust-lang/rust/
+[IntelliJ_rust_homepage]: https://intellij-rust.github.io/
+
+### Rust Analyzer
+As of [#6869][6869], [`rust-analyzer`][ra_homepage] can understand that Clippy uses compiler-internals
+using `extern crate` when `package.metadata.rust-analyzer.rustc_private` is set to `true` in Clippys `Cargo.toml.`
+You will required a `nightly` toolchain with the `rustc-dev` component installed.
+Make sure that in the `rust-analyzer` configuration, you set
+```
+{ "rust-analyzer.rustcSource": "discover" }
+```
+and
+```
+{ "rust-analyzer.updates.channel": "nightly" }
+```
+You should be able to see information on things like `Expr` or `EarlyContext` now if you hover them, also
+a lot more type hints.
+This will work with `rust-analyzer 2021-03-15` shipped in nightly `1.52.0-nightly (107896c32 2021-03-15)` or later.
+
+[ra_homepage]: https://rust-analyzer.github.io/
+[6869]: https://github.com/rust-lang/rust-clippy/pull/6869
 
 ## How Clippy works
 
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index 2b9488de289..cade44a0a9a 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.1.52"
+version = "0.1.53"
 authors = ["The Rust Clippy Developers"]
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
@@ -37,6 +37,8 @@ clippy-mini-macro-test = { version = "0.2", path = "mini-macro" }
 serde = { version = "1.0", features = ["derive"] }
 derive-new = "0.5"
 regex = "1.4"
+quote = "1"
+syn = { version = "1", features = ["full"] }
 
 # A noop dependency that changes in the Rust repository, it's a bit of a hack.
 # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
diff --git a/src/tools/clippy/clippy_dev/src/fmt.rs b/src/tools/clippy/clippy_dev/src/fmt.rs
index a26d6aba10d..111c79c332d 100644
--- a/src/tools/clippy/clippy_dev/src/fmt.rs
+++ b/src/tools/clippy/clippy_dev/src/fmt.rs
@@ -90,7 +90,7 @@ pub fn run(check: bool, verbose: bool) {
             },
             CliError::RaSetupActive => {
                 eprintln!(
-                    "error: a local rustc repo is enabled as path dependency via `cargo dev ra_setup`.
+                    "error: a local rustc repo is enabled as path dependency via `cargo dev ide_setup`.
 Not formatting because that would format the local repo as well!
 Please revert the changes to Cargo.tomls first."
                 );
diff --git a/src/tools/clippy/clippy_dev/src/ra_setup.rs b/src/tools/clippy/clippy_dev/src/ide_setup.rs
index d0e2193ddc5..defb1133e44 100644
--- a/src/tools/clippy/clippy_dev/src/ra_setup.rs
+++ b/src/tools/clippy/clippy_dev/src/ide_setup.rs
@@ -55,7 +55,7 @@ fn inject_deps_into_manifest(
     // do not inject deps if we have aleady done so
     if cargo_toml.contains("[target.'cfg(NOT_A_PLATFORM)'.dependencies]") {
         eprintln!(
-            "cargo dev ra_setup: warning: deps already found inside {}, doing nothing.",
+            "cargo dev ide_setup: warning: deps already found inside {}, doing nothing.",
             manifest_path
         );
         return Ok(());
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index a95abfaceaa..a5e94683878 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -12,8 +12,8 @@ use walkdir::WalkDir;
 
 pub mod bless;
 pub mod fmt;
+pub mod ide_setup;
 pub mod new_lint;
-pub mod ra_setup;
 pub mod serve;
 pub mod stderr_length_check;
 pub mod update_lints;
diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs
index 2a9f3e5348c..f4da783502c 100644
--- a/src/tools/clippy/clippy_dev/src/main.rs
+++ b/src/tools/clippy/clippy_dev/src/main.rs
@@ -1,7 +1,7 @@
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 
 use clap::{App, Arg, ArgMatches, SubCommand};
-use clippy_dev::{bless, fmt, new_lint, ra_setup, serve, stderr_length_check, update_lints};
+use clippy_dev::{bless, fmt, ide_setup, new_lint, serve, stderr_length_check, update_lints};
 fn main() {
     let matches = get_clap_config();
 
@@ -34,7 +34,7 @@ fn main() {
         ("limit_stderr_length", _) => {
             stderr_length_check::check();
         },
-        ("ra_setup", Some(matches)) => ra_setup::run(matches.value_of("rustc-repo-path")),
+        ("ide_setup", Some(matches)) => ide_setup::run(matches.value_of("rustc-repo-path")),
         ("serve", Some(matches)) => {
             let port = matches.value_of("port").unwrap().parse().unwrap();
             let lint = matches.value_of("lint");
@@ -138,8 +138,8 @@ fn get_clap_config<'a>() -> ArgMatches<'a> {
                 .about("Ensures that stderr files do not grow longer than a certain amount of lines."),
         )
         .subcommand(
-            SubCommand::with_name("ra_setup")
-                .about("Alter dependencies so rust-analyzer can find rustc internals")
+            SubCommand::with_name("ide_setup")
+                .about("Alter dependencies so Intellij Rust can find rustc internals")
                 .arg(
                     Arg::with_name("rustc-repo-path")
                         .long("repo-path")
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 6bd6c079276..05cdd9d064a 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "clippy_lints"
 # begin automatic update
-version = "0.1.52"
+version = "0.1.53"
 # end automatic update
 authors = ["The Rust Clippy Developers"]
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
@@ -20,7 +20,6 @@ pulldown-cmark = { version = "0.8", default-features = false }
 quine-mc_cluskey = "0.2.2"
 regex-syntax = "0.6"
 serde = { version = "1.0", features = ["derive"] }
-smallvec = { version = "1", features = ["union"] }
 toml = "0.5.3"
 unicode-normalization = "0.1"
 semver = "0.11"
@@ -28,8 +27,6 @@ rustc-semver = "1.1.0"
 # NOTE: cargo requires serde feat in its url dep
 # see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864>
 url = { version = "2.1.0", features = ["serde"] }
-quote = "1"
-syn = { version = "1", features = ["full"] }
 
 [features]
 deny-warnings = []
diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs
index 1d511a86c90..3d04abe094d 100644
--- a/src/tools/clippy/clippy_lints/src/approx_const.rs
+++ b/src/tools/clippy/clippy_lints/src/approx_const.rs
@@ -1,4 +1,4 @@
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/arithmetic.rs b/src/tools/clippy/clippy_lints/src/arithmetic.rs
index 61fdf9495b9..c560f545d6a 100644
--- a/src/tools/clippy/clippy_lints/src/arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/arithmetic.rs
@@ -1,5 +1,5 @@
 use crate::consts::constant_simple;
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
diff --git a/src/tools/clippy/clippy_lints/src/as_conversions.rs b/src/tools/clippy/clippy_lints/src/as_conversions.rs
index c30d65bbc57..4b31e16094e 100644
--- a/src/tools/clippy/clippy_lints/src/as_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/as_conversions.rs
@@ -1,10 +1,9 @@
+use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use crate::utils::span_lint_and_help;
-
 declare_clippy_lint! {
     /// **What it does:** Checks for usage of `as` conversions.
     ///
diff --git a/src/tools/clippy/clippy_lints/src/asm_syntax.rs b/src/tools/clippy/clippy_lints/src/asm_syntax.rs
index ef1f1a14afc..b970c71b753 100644
--- a/src/tools/clippy/clippy_lints/src/asm_syntax.rs
+++ b/src/tools/clippy/clippy_lints/src/asm_syntax.rs
@@ -1,6 +1,6 @@
 use std::fmt;
 
-use crate::utils::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{Expr, ExprKind, InlineAsmOptions};
 use rustc_lint::{EarlyContext, EarlyLintPass, Lint};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
index 77b26faaa58..16905781c56 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
@@ -1,5 +1,7 @@
 use crate::consts::{constant, Constant};
-use crate::utils::{is_direct_expn_of, is_expn_of, match_panic_call, snippet_opt, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::{is_direct_expn_of, is_expn_of, match_panic_call};
 use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/assign_ops.rs b/src/tools/clippy/clippy_lints/src/assign_ops.rs
index e13f62d0428..bc6eec0051a 100644
--- a/src/tools/clippy/clippy_lints/src/assign_ops.rs
+++ b/src/tools/clippy/clippy_lints/src/assign_ops.rs
@@ -1,7 +1,8 @@
-use crate::utils::{
-    eq_expr_value, get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, trait_ref_of_method,
-};
-use crate::utils::{higher, sugg};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::implements_trait;
+use clippy_utils::{eq_expr_value, get_trait_def_id, trait_ref_of_method};
+use clippy_utils::{higher, paths, sugg};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -92,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for AssignOps {
                              $($trait_name:ident),+) => {
                                 match $op {
                                     $(hir::BinOpKind::$trait_name => {
-                                        let [krate, module] = crate::utils::paths::OPS_MODULE;
+                                        let [krate, module] = paths::OPS_MODULE;
                                         let path: [&str; 3] = [krate, module, concat!(stringify!($trait_name), "Assign")];
                                         let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
                                             trait_id
diff --git a/src/tools/clippy/clippy_lints/src/async_yields_async.rs b/src/tools/clippy/clippy_lints/src/async_yields_async.rs
index 869a5c28d05..e6c7c68f91a 100644
--- a/src/tools/clippy/clippy_lints/src/async_yields_async.rs
+++ b/src/tools/clippy/clippy_lints/src/async_yields_async.rs
@@ -1,4 +1,6 @@
-use crate::utils::{implements_trait, snippet, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::implements_trait;
 use rustc_errors::Applicability;
 use rustc_hir::{AsyncGeneratorKind, Body, BodyId, ExprKind, GeneratorKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/atomic_ordering.rs b/src/tools/clippy/clippy_lints/src/atomic_ordering.rs
index 703d8a6f62b..dfb18199325 100644
--- a/src/tools/clippy/clippy_lints/src/atomic_ordering.rs
+++ b/src/tools/clippy/clippy_lints/src/atomic_ordering.rs
@@ -1,4 +1,5 @@
-use crate::utils::{match_def_path, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::match_def_path;
 use if_chain::if_chain;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, ExprKind};
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 6250810bc42..3cef8d2a78b 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -1,9 +1,8 @@
 //! checks for attributes
 
-use crate::utils::{
-    first_line_of_span, is_present_in_source, match_panic_def_id, snippet_opt, span_lint, span_lint_and_help,
-    span_lint_and_sugg, span_lint_and_then, without_block_comments,
-};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::match_panic_def_id;
+use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
 use if_chain::if_chain;
 use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
 use rustc_errors::Applicability;
@@ -431,7 +430,7 @@ fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_
         |stmt| match &stmt.kind {
             StmtKind::Local(_) => true,
             StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, typeck_results, expr),
-            _ => false,
+            StmtKind::Item(_) => false,
         },
     )
 }
@@ -565,7 +564,7 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute) {
         // check for `rustfmt_skip` and `rustfmt::skip`
         if let Some(skip_item) = &items[1].meta_item();
         if skip_item.has_name(sym!(rustfmt_skip)) ||
-            skip_item.path.segments.last().expect("empty path in attribute").ident.name == sym!(skip);
+            skip_item.path.segments.last().expect("empty path in attribute").ident.name == sym::skip;
         // Only lint outer attributes, because custom inner attributes are unstable
         // Tracking issue: https://github.com/rust-lang/rust/issues/54726
         if let AttrStyle::Outer = attr.style;
@@ -614,7 +613,7 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
                             }
                         }
                     },
-                    _ => {},
+                    MetaItemKind::NameValue(..) => {},
                 }
             }
         }
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 14b6a156c62..68eee0520b3 100644
--- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
+++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
@@ -1,4 +1,5 @@
-use crate::utils::{match_def_path, paths, span_lint_and_note};
+use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::{match_def_path, paths};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{AsyncGeneratorKind, Body, BodyId, GeneratorKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/bit_mask.rs b/src/tools/clippy/clippy_lints/src/bit_mask.rs
index a4ee54076ee..f7daf3dab49 100644
--- a/src/tools/clippy/clippy_lints/src/bit_mask.rs
+++ b/src/tools/clippy/clippy_lints/src/bit_mask.rs
@@ -1,6 +1,6 @@
 use crate::consts::{constant, Constant};
-use crate::utils::sugg::Sugg;
-use crate::utils::{span_lint, span_lint_and_then};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
+use clippy_utils::sugg::Sugg;
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/blacklisted_name.rs b/src/tools/clippy/clippy_lints/src/blacklisted_name.rs
index 153870fb416..b26ef33e056 100644
--- a/src/tools/clippy/clippy_lints/src/blacklisted_name.rs
+++ b/src/tools/clippy/clippy_lints/src/blacklisted_name.rs
@@ -1,4 +1,4 @@
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::{Pat, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
index b53f80fd8bc..badcf8d2a43 100644
--- a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
+++ b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
@@ -1,7 +1,7 @@
-use crate::utils::{
-    differing_macro_contexts, get_parent_expr, get_trait_def_id, implements_trait, paths,
-    snippet_block_with_applicability, span_lint, span_lint_and_sugg,
-};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::source::snippet_block_with_applicability;
+use clippy_utils::ty::implements_trait;
+use clippy_utils::{differing_macro_contexts, get_parent_expr};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
@@ -10,6 +10,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::map::Map;
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for `if` conditions that use blocks containing an
@@ -61,7 +62,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
                 if let Some(parent) = get_parent_expr(self.cx, expr);
                 if let ExprKind::MethodCall(_, _, args, _) = parent.kind;
                 let caller = self.cx.typeck_results().expr_ty(&args[0]);
-                if let Some(iter_id) = get_trait_def_id(self.cx, &paths::ITERATOR);
+                if let Some(iter_id) = self.cx.tcx.get_diagnostic_item(sym::Iterator);
                 if implements_trait(self.cx, caller, iter_id, &[]);
                 then {
                     return;
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index 0713303ec4b..58d9aa9c005 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -1,7 +1,7 @@
-use crate::utils::{
-    eq_expr_value, get_trait_def_id, implements_trait, in_macro, is_type_diagnostic_item, paths, snippet_opt,
-    span_lint_and_sugg, span_lint_and_then,
-};
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
+use clippy_utils::{eq_expr_value, get_trait_def_id, in_macro, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/bytecount.rs b/src/tools/clippy/clippy_lints/src/bytecount.rs
index eb5dc7ceecd..846ac08e93a 100644
--- a/src/tools/clippy/clippy_lints/src/bytecount.rs
+++ b/src/tools/clippy/clippy_lints/src/bytecount.rs
@@ -1,6 +1,7 @@
-use crate::utils::{
-    contains_name, get_pat_name, match_type, paths, single_segment_path, snippet_with_applicability, span_lint_and_sugg,
-};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::match_type;
+use clippy_utils::{contains_name, get_pat_name, paths, single_segment_path};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, UnOp};
diff --git a/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs b/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs
index cc2869ab495..fce5c559672 100644
--- a/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs
@@ -2,7 +2,8 @@
 
 use std::path::PathBuf;
 
-use crate::utils::{run_lints, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::run_lints;
 use rustc_hir::{hir_id::CRATE_HIR_ID, Crate};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
diff --git a/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs
index b15fe65352a..c9ef379be56 100644
--- a/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs
@@ -1,4 +1,4 @@
-use crate::utils::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_help;
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_hir::{Expr, ExprKind, PathSegment};
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
index 478832a5164..869deecfbd5 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
@@ -1,10 +1,12 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::in_constant;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::is_isize_or_usize;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, FloatTy, Ty};
 
-use crate::utils::{in_constant, is_isize_or_usize, snippet_opt, span_lint_and_sugg};
-
 use super::{utils, CAST_LOSSLESS};
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
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 33b06b8fe7c..833ad122e0d 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
@@ -1,9 +1,9 @@
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::ty::is_isize_or_usize;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, FloatTy, Ty};
 
-use crate::utils::{is_isize_or_usize, span_lint};
-
 use super::{utils, CAST_POSSIBLE_TRUNCATION};
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
index 56d301ed3e1..2c5c1d7cb46 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
@@ -1,9 +1,9 @@
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::ty::is_isize_or_usize;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::Ty;
 
-use crate::utils::{is_isize_or_usize, span_lint};
-
 use super::{utils, CAST_POSSIBLE_WRAP};
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs
index a1c3900ce1f..63ac8fd2dd2 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs
@@ -1,9 +1,9 @@
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::ty::is_isize_or_usize;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, FloatTy, Ty};
 
-use crate::utils::{is_isize_or_usize, span_lint};
-
 use super::{utils, CAST_PRECISION_LOSS};
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
index 87fb5557be0..5208156ffd2 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
@@ -1,13 +1,12 @@
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::is_hir_ty_cfg_dependant;
+use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, GenericArg};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::sym;
 use rustc_target::abi::LayoutOf;
 
-use if_chain::if_chain;
-
-use crate::utils::{is_hir_ty_cfg_dependant, span_lint};
-
 use super::CAST_PTR_ALIGNMENT;
 
 pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ref_to_mut.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ref_to_mut.rs
index 3fdc1c6168b..d9bf1ea58b9 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_ref_to_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_ref_to_mut.rs
@@ -1,11 +1,9 @@
+use clippy_utils::diagnostics::span_lint;
+use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, MutTy, Mutability, TyKind, UnOp};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 
-use if_chain::if_chain;
-
-use crate::utils::span_lint;
-
 use super::CAST_REF_TO_MUT;
 
 pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
index 9656fbebd77..bf722d0a3f4 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
@@ -1,12 +1,11 @@
+use crate::consts::{constant, Constant};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{method_chain_args, sext};
+use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
 
-use if_chain::if_chain;
-
-use crate::consts::{constant, Constant};
-use crate::utils::{method_chain_args, sext, span_lint};
-
 use super::CAST_SIGN_LOSS;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs b/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs
index ccaad1b8f2a..099a0de881f 100644
--- a/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs
@@ -1,13 +1,12 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet_with_applicability;
+use if_chain::if_chain;
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, UintTy};
 
-use if_chain::if_chain;
-
-use crate::utils::{snippet_with_applicability, span_lint_and_then};
-
 use super::CHAR_LIT_AS_U8;
 
 pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs
index a8d508585b5..35350d8a25b 100644
--- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs
@@ -1,10 +1,10 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty, UintTy};
 
-use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
-
 use super::{utils, FN_TO_NUMERIC_CAST};
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
index 0085c7b27b2..6287f479b5b 100644
--- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
@@ -1,10 +1,10 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
 
-use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
-
 use super::{utils, FN_TO_NUMERIC_CAST_WITH_TRUNCATION};
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index b726bd75f1d..d9e172c01a7 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -12,14 +12,13 @@ mod ptr_as_ptr;
 mod unnecessary_cast;
 mod utils;
 
+use clippy_utils::is_hir_ty_cfg_dependant;
 use rustc_hir::{Expr, ExprKind};
 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 crate::utils::is_hir_ty_cfg_dependant;
-
 declare_clippy_lint! {
     /// **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
diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
index abfbadf3642..9113e5a0920 100644
--- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
@@ -1,16 +1,15 @@
 use std::borrow::Cow;
 
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::meets_msrv;
+use clippy_utils::sugg::Sugg;
+use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Mutability, TyKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, TypeAndMut};
 use rustc_semver::RustcVersion;
 
-use if_chain::if_chain;
-
-use crate::utils::sugg::Sugg;
-use crate::utils::{meets_msrv, span_lint_and_sugg};
-
 use super::PTR_AS_PTR;
 
 const PTR_AS_PTR_MSRV: RustcVersion = RustcVersion::new(1, 38, 0);
diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
index fa2a07ef1da..9ed359922fd 100644
--- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
@@ -1,3 +1,7 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::numeric_literal::NumericLiteral;
+use clippy_utils::source::snippet_opt;
+use if_chain::if_chain;
 use rustc_ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Lit, UnOp};
@@ -5,10 +9,6 @@ use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, FloatTy, InferTy, Ty};
 
-use if_chain::if_chain;
-
-use crate::utils::{numeric_literal::NumericLiteral, snippet_opt, span_lint, span_lint_and_sugg};
-
 use super::UNNECESSARY_CAST;
 
 pub(super) fn check(
@@ -44,9 +44,18 @@ pub(super) fn check(
                 lint_unnecessary_cast(cx, expr, &literal_str, cast_from, cast_to);
             },
             LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed) => {},
+            LitKind::Int(_, LitIntType::Signed(_) | LitIntType::Unsigned(_))
+            | LitKind::Float(_, LitFloatType::Suffixed(_))
+                if cast_from.kind() == cast_to.kind() =>
+            {
+                if let Some(src) = snippet_opt(cx, lit.span) {
+                    let num_lit = NumericLiteral::from_lit_kind(&src, &lit.node).unwrap();
+                    lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
+                }
+            },
             _ => {
                 if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) {
-                    span_lint(
+                    span_lint_and_sugg(
                         cx,
                         UNNECESSARY_CAST,
                         expr.span,
@@ -54,6 +63,9 @@ pub(super) fn check(
                             "casting to the same type is unnecessary (`{}` -> `{}`)",
                             cast_from, cast_to
                         ),
+                        "try",
+                        literal_str,
+                        Applicability::MachineApplicable,
                     );
                     return true;
                 }
diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
index 54bc69e058b..ed46cac493a 100644
--- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
@@ -1,5 +1,8 @@
 //! lint on manually implemented checked conversions that could be transformed into `try_from`
 
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::{meets_msrv, SpanlessEq};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
@@ -9,8 +12,6 @@ use rustc_middle::lint::in_external_macro;
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 
-use crate::utils::{meets_msrv, snippet_with_applicability, span_lint_and_sugg, SpanlessEq};
-
 const CHECKED_CONVERSIONS_MSRV: RustcVersion = RustcVersion::new(1, 34, 0);
 
 declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
index 658d445dfec..4cc542f723c 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
@@ -1,5 +1,9 @@
 //! calculate cognitive complexity and warn about overly complex functions
 
+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::LimitStack;
 use rustc_ast::ast::Attribute;
 use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor};
 use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId};
@@ -9,8 +13,6 @@ use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
 use rustc_span::{sym, BytePos};
 
-use crate::utils::{is_type_diagnostic_item, snippet_opt, span_lint_and_help, LimitStack};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for methods with high cognitive complexity.
     ///
diff --git a/src/tools/clippy/clippy_lints/src/collapsible_if.rs b/src/tools/clippy/clippy_lints/src/collapsible_if.rs
index 34f0e6ab027..dae5c86bd44 100644
--- a/src/tools/clippy/clippy_lints/src/collapsible_if.rs
+++ b/src/tools/clippy/clippy_lints/src/collapsible_if.rs
@@ -12,15 +12,15 @@
 //!
 //! This lint is **warn** by default
 
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::source::{snippet_block, snippet_block_with_applicability};
+use clippy_utils::sugg::Sugg;
 use if_chain::if_chain;
 use rustc_ast::ast;
+use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use crate::utils::sugg::Sugg;
-use crate::utils::{snippet_block, snippet_block_with_applicability, span_lint_and_sugg, span_lint_and_then};
-use rustc_errors::Applicability;
-
 declare_clippy_lint! {
     /// **What it does:** Checks for nested `if` statements which can be collapsed
     /// by `&&`-combining their conditions.
diff --git a/src/tools/clippy/clippy_lints/src/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/collapsible_match.rs
index 3c45525684b..e2b3686ddf0 100644
--- a/src/tools/clippy/clippy_lints/src/collapsible_match.rs
+++ b/src/tools/clippy/clippy_lints/src/collapsible_match.rs
@@ -1,5 +1,6 @@
-use crate::utils::visitors::LocalUsedVisitor;
-use crate::utils::{path_to_local, span_lint_and_then, SpanlessEq};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::visitors::LocalUsedVisitor;
+use clippy_utils::{path_to_local, SpanlessEq};
 use if_chain::if_chain;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, QPath, StmtKind, UnOp};
diff --git a/src/tools/clippy/clippy_lints/src/comparison_chain.rs b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
index e309db25995..d601cb7c224 100644
--- a/src/tools/clippy/clippy_lints/src/comparison_chain.rs
+++ b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
@@ -1,6 +1,6 @@
-use crate::utils::{
-    get_trait_def_id, if_sequence, implements_trait, parent_node_is_if_expr, paths, span_lint_and_help, SpanlessEq,
-};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::ty::implements_trait;
+use clippy_utils::{get_trait_def_id, if_sequence, parent_node_is_if_expr, paths, SpanlessEq};
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index 944aaafb46d..46093a16571 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -1,5 +1,6 @@
-use crate::utils::{eq_expr_value, in_macro, search_same, SpanlessEq, SpanlessHash};
-use crate::utils::{get_parent_expr, if_sequence, span_lint_and_note};
+use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::{eq_expr_value, in_macro, search_same, SpanlessEq, SpanlessHash};
+use clippy_utils::{get_parent_expr, if_sequence};
 use rustc_hir::{Block, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/copy_iterator.rs b/src/tools/clippy/clippy_lints/src/copy_iterator.rs
index 004bce5f62a..35079c6bedc 100644
--- a/src/tools/clippy/clippy_lints/src/copy_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/copy_iterator.rs
@@ -1,7 +1,11 @@
-use crate::utils::{is_copy, match_path, paths, span_lint_and_note};
+use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::ty::is_copy;
 use rustc_hir::{Impl, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
+
+use if_chain::if_chain;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for types that implement `Copy` as well as
@@ -33,14 +37,16 @@ declare_lint_pass!(CopyIterator => [COPY_ITERATOR]);
 
 impl<'tcx> LateLintPass<'tcx> for CopyIterator {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if let ItemKind::Impl(Impl {
-            of_trait: Some(ref trait_ref),
-            ..
-        }) = item.kind
-        {
+        if_chain! {
+            if let ItemKind::Impl(Impl {
+                of_trait: Some(ref trait_ref),
+                ..
+            }) = item.kind;
             let ty = cx.tcx.type_of(item.def_id);
-
-            if is_copy(cx, ty) && match_path(&trait_ref.path, &paths::ITERATOR) {
+            if is_copy(cx, ty);
+            if let Some(trait_id) = trait_ref.trait_def_id();
+            if cx.tcx.is_diagnostic_item(sym::Iterator, trait_id);
+            then {
                 span_lint_and_note(
                     cx,
                     COPY_ITERATOR,
diff --git a/src/tools/clippy/clippy_lints/src/create_dir.rs b/src/tools/clippy/clippy_lints/src/create_dir.rs
index 200b6a565cc..ac890c90c97 100644
--- a/src/tools/clippy/clippy_lints/src/create_dir.rs
+++ b/src/tools/clippy/clippy_lints/src/create_dir.rs
@@ -1,4 +1,6 @@
-use crate::utils::{match_def_path, paths, snippet, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
index e513dcce64e..286cc7e223e 100644
--- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs
+++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
@@ -1,4 +1,5 @@
-use crate::utils::{snippet_opt, span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::source::snippet_opt;
 use rustc_ast::ast;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs
index 6fa1378b8c7..568a174445c 100644
--- a/src/tools/clippy/clippy_lints/src/default.rs
+++ b/src/tools/clippy/clippy_lints/src/default.rs
@@ -1,7 +1,6 @@
-use crate::utils::{
-    any_parent_is_automatically_derived, contains_name, match_def_path, paths, snippet_with_macro_callsite,
-};
-use crate::utils::{span_lint_and_note, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
+use clippy_utils::source::snippet_with_macro_callsite;
+use clippy_utils::{any_parent_is_automatically_derived, contains_name, match_def_path, paths};
 use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
@@ -105,6 +104,7 @@ impl LateLintPass<'_> for Default {
         }
     }
 
+    #[allow(clippy::too_many_lines)]
     fn check_block<'tcx>(&mut self, cx: &LateContext<'tcx>, block: &Block<'tcx>) {
         // start from the `let mut _ = _::default();` and look at all the following
         // statements, see if they re-assign the fields of the binding
@@ -198,6 +198,24 @@ impl LateLintPass<'_> for Default {
                     .collect::<Vec<String>>()
                     .join(", ");
 
+                // give correct suggestion if generics are involved (see #6944)
+                let binding_type = if_chain! {
+                    if let ty::Adt(adt_def, substs) = binding_type.kind();
+                    if !substs.is_empty();
+                    let adt_def_ty_name = cx.tcx.item_name(adt_def.did);
+                    let generic_args = substs.iter().collect::<Vec<_>>();
+                    let tys_str = generic_args
+                        .iter()
+                        .map(ToString::to_string)
+                        .collect::<Vec<_>>()
+                        .join(", ");
+                    then {
+                        format!("{}::<{}>", adt_def_ty_name, &tys_str)
+                    } else {
+                        binding_type.to_string()
+                    }
+                };
+
                 let sugg = if ext_with_default {
                     if field_list.is_empty() {
                         format!("{}::default()", binding_type)
diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
index 369efacc9bc..73f71d88b05 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -1,3 +1,6 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use if_chain::if_chain;
 use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir::{
@@ -10,10 +13,7 @@ use rustc_middle::{
     ty::{self, FloatTy, IntTy, PolyFnSig, Ty},
 };
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-
-use if_chain::if_chain;
-
-use crate::utils::{snippet, span_lint_and_sugg};
+use std::iter;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for usage of unconstrained numeric literals which may cause default numeric fallback in type
@@ -108,7 +108,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
         match &expr.kind {
             ExprKind::Call(func, args) => {
                 if let Some(fn_sig) = fn_sig_opt(self.cx, func.hir_id) {
-                    for (expr, bound) in args.iter().zip(fn_sig.skip_binder().inputs().iter()) {
+                    for (expr, bound) in iter::zip(*args, fn_sig.skip_binder().inputs()) {
                         // Push found arg type, then visit arg.
                         self.ty_bounds.push(TyBound::Ty(bound));
                         self.visit_expr(expr);
@@ -121,7 +121,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
             ExprKind::MethodCall(_, _, args, _) => {
                 if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) {
                     let fn_sig = self.cx.tcx.fn_sig(def_id).skip_binder();
-                    for (expr, bound) in args.iter().zip(fn_sig.inputs().iter()) {
+                    for (expr, bound) in iter::zip(*args, fn_sig.inputs()) {
                         self.ty_bounds.push(TyBound::Ty(bound));
                         self.visit_expr(expr);
                         self.ty_bounds.pop();
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index b5fb51af1c7..1415f8e235a 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -1,11 +1,14 @@
-use crate::utils::{get_parent_expr, implements_trait, snippet, span_lint_and_sugg};
-use if_chain::if_chain;
-use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX, PREC_PREFIX};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_context;
+use clippy_utils::ty::peel_mid_ty_refs;
+use clippy_utils::{get_parent_node, in_macro, is_allowed};
+use rustc_ast::util::parser::PREC_PREFIX;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind};
+use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::source_map::Span;
+use rustc_middle::ty::{self, Ty, TyCtxt, TyS, TypeckResults};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{symbol::sym, Span};
 
 declare_clippy_lint! {
     /// **What it does:** Checks for explicit `deref()` or `deref_mut()` method calls.
@@ -34,76 +37,265 @@ declare_clippy_lint! {
     "Explicit use of deref or deref_mut method while not in a method chain."
 }
 
-declare_lint_pass!(Dereferencing => [
-    EXPLICIT_DEREF_METHODS
+impl_lint_pass!(Dereferencing => [
+    EXPLICIT_DEREF_METHODS,
 ]);
 
+#[derive(Default)]
+pub struct Dereferencing {
+    state: Option<(State, StateData)>,
+
+    // While parsing a `deref` method call in ufcs form, the path to the function is itself an
+    // expression. This is to store the id of that expression so it can be skipped when
+    // `check_expr` is called for it.
+    skip_expr: Option<HirId>,
+}
+
+struct StateData {
+    /// Span of the top level expression
+    span: Span,
+    /// The required mutability
+    target_mut: Mutability,
+}
+
+enum State {
+    // Any number of deref method calls.
+    DerefMethod {
+        // The number of calls in a sequence which changed the referenced type
+        ty_changed_count: usize,
+        is_final_ufcs: bool,
+    },
+}
+
+// A reference operation considered by this lint pass
+enum RefOp {
+    Method(Mutability),
+    Deref,
+    AddrOf,
+}
+
 impl<'tcx> LateLintPass<'tcx> for Dereferencing {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if_chain! {
-            if !expr.span.from_expansion();
-            if let ExprKind::MethodCall(ref method_name, _, ref args, _) = &expr.kind;
-            if args.len() == 1;
-
-            then {
-                if let Some(parent_expr) = get_parent_expr(cx, expr) {
-                    // Check if we have the whole call chain here
-                    if let ExprKind::MethodCall(..) = parent_expr.kind {
-                        return;
-                    }
-                    // Check for Expr that we don't want to be linted
-                    let precedence = parent_expr.precedence();
-                    match precedence {
-                        // Lint a Call is ok though
-                        ExprPrecedence::Call | ExprPrecedence::AddrOf => (),
-                        _ => {
-                            if precedence.order() >= PREC_PREFIX && precedence.order() <= PREC_POSTFIX {
-                                return;
-                            }
-                        }
+        // Skip path expressions from deref calls. e.g. `Deref::deref(e)`
+        if Some(expr.hir_id) == self.skip_expr.take() {
+            return;
+        }
+
+        // Stop processing sub expressions when a macro call is seen
+        if in_macro(expr.span) {
+            if let Some((state, data)) = self.state.take() {
+                report(cx, expr, state, data);
+            }
+            return;
+        }
+
+        let typeck = cx.typeck_results();
+        let (kind, sub_expr) = if let Some(x) = try_parse_ref_op(cx.tcx, typeck, expr) {
+            x
+        } else {
+            // The whole chain of reference operations has been seen
+            if let Some((state, data)) = self.state.take() {
+                report(cx, expr, state, data);
+            }
+            return;
+        };
+
+        match (self.state.take(), kind) {
+            (None, kind) => {
+                let parent = get_parent_node(cx.tcx, expr.hir_id);
+                let expr_ty = typeck.expr_ty(expr);
+
+                match kind {
+                    RefOp::Method(target_mut)
+                        if !is_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id)
+                            && is_linted_explicit_deref_position(parent, expr.hir_id, expr.span) =>
+                    {
+                        self.state = Some((
+                            State::DerefMethod {
+                                ty_changed_count: if deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr)) {
+                                    0
+                                } else {
+                                    1
+                                },
+                                is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)),
+                            },
+                            StateData {
+                                span: expr.span,
+                                target_mut,
+                            },
+                        ));
                     }
+                    _ => (),
                 }
-                let name = method_name.ident.as_str();
-                lint_deref(cx, &*name, &args[0], args[0].span, expr.span);
-            }
+            },
+            (Some((State::DerefMethod { ty_changed_count, .. }, data)), RefOp::Method(_)) => {
+                self.state = Some((
+                    State::DerefMethod {
+                        ty_changed_count: if deref_method_same_type(typeck.expr_ty(expr), typeck.expr_ty(sub_expr)) {
+                            ty_changed_count
+                        } else {
+                            ty_changed_count + 1
+                        },
+                        is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)),
+                    },
+                    data,
+                ));
+            },
+
+            (Some((state, data)), _) => report(cx, expr, state, data),
         }
     }
 }
 
-fn lint_deref(cx: &LateContext<'_>, method_name: &str, call_expr: &Expr<'_>, var_span: Span, expr_span: Span) {
-    match method_name {
-        "deref" => {
-            let impls_deref_trait = cx.tcx.lang_items().deref_trait().map_or(false, |id| {
-                implements_trait(cx, cx.typeck_results().expr_ty(&call_expr), id, &[])
-            });
-            if impls_deref_trait {
-                span_lint_and_sugg(
-                    cx,
-                    EXPLICIT_DEREF_METHODS,
-                    expr_span,
-                    "explicit deref method call",
-                    "try this",
-                    format!("&*{}", &snippet(cx, var_span, "..")),
-                    Applicability::MachineApplicable,
-                );
-            }
+fn try_parse_ref_op(
+    tcx: TyCtxt<'tcx>,
+    typeck: &'tcx TypeckResults<'_>,
+    expr: &'tcx Expr<'_>,
+) -> Option<(RefOp, &'tcx Expr<'tcx>)> {
+    let (def_id, arg) = match expr.kind {
+        ExprKind::MethodCall(_, _, [arg], _) => (typeck.type_dependent_def_id(expr.hir_id)?, arg),
+        ExprKind::Call(
+            Expr {
+                kind: ExprKind::Path(path),
+                hir_id,
+                ..
+            },
+            [arg],
+        ) => (typeck.qpath_res(path, *hir_id).opt_def_id()?, arg),
+        ExprKind::Unary(UnOp::Deref, sub_expr) if !typeck.expr_ty(sub_expr).is_unsafe_ptr() => {
+            return Some((RefOp::Deref, sub_expr));
         },
-        "deref_mut" => {
-            let impls_deref_mut_trait = cx.tcx.lang_items().deref_mut_trait().map_or(false, |id| {
-                implements_trait(cx, cx.typeck_results().expr_ty(&call_expr), id, &[])
-            });
-            if impls_deref_mut_trait {
-                span_lint_and_sugg(
-                    cx,
-                    EXPLICIT_DEREF_METHODS,
-                    expr_span,
-                    "explicit deref_mut method call",
-                    "try this",
-                    format!("&mut *{}", &snippet(cx, var_span, "..")),
-                    Applicability::MachineApplicable,
-                );
-            }
+        ExprKind::AddrOf(BorrowKind::Ref, _, sub_expr) => return Some((RefOp::AddrOf, sub_expr)),
+        _ => return None,
+    };
+    if tcx.is_diagnostic_item(sym::deref_method, def_id) {
+        Some((RefOp::Method(Mutability::Not), arg))
+    } else if tcx.trait_of_item(def_id)? == tcx.lang_items().deref_mut_trait()? {
+        Some((RefOp::Method(Mutability::Mut), arg))
+    } else {
+        None
+    }
+}
+
+// Checks whether the type for a deref call actually changed the type, not just the mutability of
+// the reference.
+fn deref_method_same_type(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
+    match (result_ty.kind(), arg_ty.kind()) {
+        (ty::Ref(_, result_ty, _), ty::Ref(_, arg_ty, _)) => TyS::same_type(result_ty, arg_ty),
+
+        // The result type for a deref method is always a reference
+        // Not matching the previous pattern means the argument type is not a reference
+        // This means that the type did change
+        _ => false,
+    }
+}
+
+// Checks whether the parent node is a suitable context for switching from a deref method to the
+// deref operator.
+fn is_linted_explicit_deref_position(parent: Option<Node<'_>>, child_id: HirId, child_span: Span) -> bool {
+    let parent = match parent {
+        Some(Node::Expr(e)) if e.span.ctxt() == child_span.ctxt() => e,
+        _ => return true,
+    };
+    match parent.kind {
+        // Leave deref calls in the middle of a method chain.
+        // e.g. x.deref().foo()
+        ExprKind::MethodCall(_, _, [self_arg, ..], _) if self_arg.hir_id == child_id => false,
+
+        // Leave deref calls resulting in a called function
+        // e.g. (x.deref())()
+        ExprKind::Call(func_expr, _) if func_expr.hir_id == child_id => false,
+
+        // Makes an ugly suggestion
+        // e.g. *x.deref() => *&*x
+        ExprKind::Unary(UnOp::Deref, _)
+        // Postfix expressions would require parens
+        | ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
+        | ExprKind::Field(..)
+        | ExprKind::Index(..)
+        | ExprKind::Err => false,
+
+        ExprKind::Box(..)
+        | ExprKind::ConstBlock(..)
+        | ExprKind::Array(_)
+        | ExprKind::Call(..)
+        | ExprKind::MethodCall(..)
+        | ExprKind::Tup(..)
+        | ExprKind::Binary(..)
+        | ExprKind::Unary(..)
+        | ExprKind::Lit(..)
+        | ExprKind::Cast(..)
+        | ExprKind::Type(..)
+        | ExprKind::DropTemps(..)
+        | ExprKind::If(..)
+        | ExprKind::Loop(..)
+        | ExprKind::Match(..)
+        | ExprKind::Closure(..)
+        | ExprKind::Block(..)
+        | ExprKind::Assign(..)
+        | ExprKind::AssignOp(..)
+        | ExprKind::Path(..)
+        | ExprKind::AddrOf(..)
+        | ExprKind::Break(..)
+        | ExprKind::Continue(..)
+        | ExprKind::Ret(..)
+        | ExprKind::InlineAsm(..)
+        | ExprKind::LlvmInlineAsm(..)
+        | ExprKind::Struct(..)
+        | ExprKind::Repeat(..)
+        | ExprKind::Yield(..) => true,
+    }
+}
+
+#[allow(clippy::needless_pass_by_value)]
+fn report(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data: StateData) {
+    match state {
+        State::DerefMethod {
+            ty_changed_count,
+            is_final_ufcs,
+        } => {
+            let mut app = Applicability::MachineApplicable;
+            let (expr_str, expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
+            let ty = cx.typeck_results().expr_ty(expr);
+            let (_, ref_count) = peel_mid_ty_refs(ty);
+            let deref_str = if ty_changed_count >= ref_count && ref_count != 0 {
+                // a deref call changing &T -> &U requires two deref operators the first time
+                // this occurs. One to remove the reference, a second to call the deref impl.
+                "*".repeat(ty_changed_count + 1)
+            } else {
+                "*".repeat(ty_changed_count)
+            };
+            let addr_of_str = if ty_changed_count < ref_count {
+                // Check if a reborrow from &mut T -> &T is required.
+                if data.target_mut == Mutability::Not && matches!(ty.kind(), ty::Ref(_, _, Mutability::Mut)) {
+                    "&*"
+                } else {
+                    ""
+                }
+            } else if data.target_mut == Mutability::Mut {
+                "&mut "
+            } else {
+                "&"
+            };
+
+            let expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX {
+                format!("({})", expr_str)
+            } else {
+                expr_str.into_owned()
+            };
+
+            span_lint_and_sugg(
+                cx,
+                EXPLICIT_DEREF_METHODS,
+                data.span,
+                match data.target_mut {
+                    Mutability::Not => "explicit `deref` method call",
+                    Mutability::Mut => "explicit `deref_mut` method call",
+                },
+                "try this",
+                format!("{}{}{}", addr_of_str, deref_str, expr_str),
+                app,
+            );
         },
-        _ => (),
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 6d3094ed6bf..834136f910d 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -1,8 +1,7 @@
-use crate::utils::paths;
-use crate::utils::{
-    get_trait_def_id, is_allowed, is_automatically_derived, is_copy, match_def_path, span_lint_and_help,
-    span_lint_and_note, span_lint_and_then,
-};
+use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_then};
+use clippy_utils::paths;
+use clippy_utils::ty::is_copy;
+use clippy_utils::{get_trait_def_id, is_allowed, is_automatically_derived, match_def_path};
 use if_chain::if_chain;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor};
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_method.rs b/src/tools/clippy/clippy_lints/src/disallowed_method.rs
index 56dc6d18a58..ded0a0fff54 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_method.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_method.rs
@@ -1,4 +1,5 @@
-use crate::utils::{fn_def_id, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::fn_def_id;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::Expr;
diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs
index 90b02d52f8a..14338ac8faf 100644
--- a/src/tools/clippy/clippy_lints/src/doc.rs
+++ b/src/tools/clippy/clippy_lints/src/doc.rs
@@ -1,7 +1,6 @@
-use crate::utils::{
-    implements_trait, is_entrypoint_fn, is_expn_of, is_type_diagnostic_item, match_panic_def_id, method_chain_args,
-    return_ty, span_lint, span_lint_and_note,
-};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_note};
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
+use clippy_utils::{is_entrypoint_fn, is_expn_of, match_panic_def_id, method_chain_args, return_ty};
 use if_chain::if_chain;
 use itertools::Itertools;
 use rustc_ast::ast::{Async, AttrKind, Attribute, FnKind, FnRetTy, ItemKind};
@@ -584,7 +583,7 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
                                 let returns_nothing = match &sig.decl.output {
                                     FnRetTy::Default(..) => true,
                                     FnRetTy::Ty(ty) if ty.kind.is_unit() => true,
-                                    _ => false,
+                                    FnRetTy::Ty(_) => false,
                                 };
 
                                 if returns_nothing && !is_async && !block.stmts.is_empty() {
diff --git a/src/tools/clippy/clippy_lints/src/double_comparison.rs b/src/tools/clippy/clippy_lints/src/double_comparison.rs
index 19f56195ec1..1d291565ec1 100644
--- a/src/tools/clippy/clippy_lints/src/double_comparison.rs
+++ b/src/tools/clippy/clippy_lints/src/double_comparison.rs
@@ -1,13 +1,14 @@
 //! Lint on unnecessary double comparisons. Some examples:
 
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::eq_expr_value;
+use clippy_utils::source::snippet_with_applicability;
 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::Span;
 
-use crate::utils::{eq_expr_value, snippet_with_applicability, span_lint_and_sugg};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for double comparisons that could be simplified to a single expression.
     ///
diff --git a/src/tools/clippy/clippy_lints/src/double_parens.rs b/src/tools/clippy/clippy_lints/src/double_parens.rs
index abbcaf43f41..5afdcb3c09f 100644
--- a/src/tools/clippy/clippy_lints/src/double_parens.rs
+++ b/src/tools/clippy/clippy_lints/src/double_parens.rs
@@ -1,4 +1,4 @@
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
index 2aea00d883c..7e7ec017bbb 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -1,4 +1,6 @@
-use crate::utils::{is_copy, match_def_path, paths, span_lint_and_note};
+use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::ty::is_copy;
+use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/duration_subsec.rs
index c0529a34cc4..746c1f6df91 100644
--- a/src/tools/clippy/clippy_lints/src/duration_subsec.rs
+++ b/src/tools/clippy/clippy_lints/src/duration_subsec.rs
@@ -1,3 +1,5 @@
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::match_type;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
@@ -6,8 +8,8 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Spanned;
 
 use crate::consts::{constant, Constant};
-use crate::utils::paths;
-use crate::utils::{match_type, snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::paths;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for calculation of subsecond microseconds or milliseconds
diff --git a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs
index 95123e6ff6f..26984df9539 100644
--- a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs
+++ b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs
@@ -1,12 +1,11 @@
 //! Lint on if expressions with an else if, but without a final else branch.
 
+use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use crate::utils::span_lint_and_help;
-
 declare_clippy_lint! {
     /// **What it does:** Checks for usage of if expressions with an `else if` branch,
     /// but without a final `else` branch.
diff --git a/src/tools/clippy/clippy_lints/src/empty_enum.rs b/src/tools/clippy/clippy_lints/src/empty_enum.rs
index 077c3b75fb8..c92984a9834 100644
--- a/src/tools/clippy/clippy_lints/src/empty_enum.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_enum.rs
@@ -1,6 +1,6 @@
 //! lint when there is an enum with no variants
 
-use crate::utils::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index 55575969927..25eb048448c 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -1,6 +1,8 @@
-use crate::utils::SpanlessEq;
-use crate::utils::{get_item_name, is_type_diagnostic_item, match_type, paths, snippet, snippet_opt};
-use crate::utils::{snippet_with_applicability, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
+use clippy_utils::ty::{is_type_diagnostic_item, match_type};
+use clippy_utils::SpanlessEq;
+use clippy_utils::{get_item_name, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs
index aa235642ac3..7a98ae39d3a 100644
--- a/src/tools/clippy/clippy_lints/src/enum_clike.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs
@@ -2,7 +2,7 @@
 //! don't fit into an `i32`
 
 use crate::consts::{miri_to_const, Constant};
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::util::IntTypeExt;
diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs
index 67a46353856..0ecc0bc3eb6 100644
--- a/src/tools/clippy/clippy_lints/src/enum_variants.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs
@@ -1,7 +1,8 @@
 //! lint on enum variants that are prefixed or suffixed by the same characters
 
-use crate::utils::{camel_case, is_present_in_source};
-use crate::utils::{span_lint, span_lint_and_help};
+use clippy_utils::camel_case;
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::source::is_present_in_source;
 use rustc_ast::ast::{EnumDef, Item, ItemKind, VisibilityKind};
 use rustc_lint::{EarlyContext, EarlyLintPass, Lint};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
diff --git a/src/tools/clippy/clippy_lints/src/eq_op.rs b/src/tools/clippy/clippy_lints/src/eq_op.rs
index 6308f6e2e7e..6d7046ac8b7 100644
--- a/src/tools/clippy/clippy_lints/src/eq_op.rs
+++ b/src/tools/clippy/clippy_lints/src/eq_op.rs
@@ -1,7 +1,7 @@
-use crate::utils::{
-    ast_utils::is_useless_with_eq_exprs, eq_expr_value, higher, implements_trait, in_macro, is_copy, is_expn_of,
-    multispan_sugg, snippet, span_lint, span_lint_and_then,
-};
+use clippy_utils::diagnostics::{multispan_sugg, span_lint, span_lint_and_then};
+use clippy_utils::source::snippet;
+use clippy_utils::ty::{implements_trait, is_copy};
+use clippy_utils::{ast_utils::is_useless_with_eq_exprs, eq_expr_value, higher, in_macro, is_expn_of};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, StmtKind};
diff --git a/src/tools/clippy/clippy_lints/src/erasing_op.rs b/src/tools/clippy/clippy_lints/src/erasing_op.rs
index dbd1ff514f0..59602616781 100644
--- a/src/tools/clippy/clippy_lints/src/erasing_op.rs
+++ b/src/tools/clippy/clippy_lints/src/erasing_op.rs
@@ -1,10 +1,10 @@
+use clippy_utils::diagnostics::span_lint;
 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::Span;
 
 use crate::consts::{constant_simple, Constant};
-use crate::utils::span_lint;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for erasing operations, e.g., `x * 0`.
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index 97216757547..3581ab41906 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -1,3 +1,5 @@
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::ty::contains_ty;
 use rustc_hir::intravisit;
 use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node};
 use rustc_infer::infer::TyCtxtInferExt;
@@ -11,8 +13,6 @@ use rustc_target::abi::LayoutOf;
 use rustc_target::spec::abi::Abi;
 use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
-use crate::utils::{contains_ty, span_lint};
-
 #[derive(Copy, Clone)]
 pub struct BoxedLocal {
     pub too_large_for_stack: u64,
@@ -186,7 +186,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
         }
     }
 
-    fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) { }
+    fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) {}
 }
 
 impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index c461732fd36..99253555a95 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -1,3 +1,9 @@
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::higher;
+use clippy_utils::higher::VecArgs;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::{implements_trait, type_is_unsafe_function};
+use clippy_utils::{is_adjusted, iter_input_pats};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{def_id, Expr, ExprKind, Param, PatKind, QPath};
@@ -6,13 +12,6 @@ use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use crate::utils::{
-    implements_trait, is_adjusted, iter_input_pats, snippet_opt, span_lint_and_sugg, span_lint_and_then,
-    type_is_unsafe_function,
-};
-use clippy_utils::higher;
-use clippy_utils::higher::VecArgs;
-
 declare_clippy_lint! {
     /// **What it does:** Checks for closures which just call another function where
     /// the function can be called directly. `unsafe` functions or calls where types
diff --git a/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs b/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs
index 83cee11c3a8..ea33a4d98fd 100644
--- a/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs
+++ b/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs
@@ -1,4 +1,5 @@
-use crate::utils::{get_parent_expr, path_to_local, path_to_local_id, span_lint, span_lint_and_note};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_note};
+use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id};
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Guard, HirId, Local, Node, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -272,7 +273,7 @@ fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt<'_>) -
             .init
             .as_ref()
             .map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)),
-        _ => StopEarly::KeepGoing,
+        StmtKind::Item(..) => StopEarly::KeepGoing,
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs
index 6f22f65deac..6c9652fd87d 100644
--- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs
+++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs
@@ -1,7 +1,6 @@
-use crate::utils::{attr_by_name, in_macro, match_path_ast, span_lint_and_help};
-use rustc_ast::ast::{
-    AssocItemKind, Extern, FnKind, FnSig, ImplKind, Item, ItemKind, TraitKind, Ty, TyKind,
-};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::{attr_by_name, in_macro, match_path_ast};
+use rustc_ast::ast::{AssocItemKind, Extern, FnKind, FnSig, ImplKind, Item, ItemKind, TraitKind, Ty, TyKind};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::Span;
diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
index 316f7484862..60ad2e8ee14 100644
--- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
+++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
@@ -1,4 +1,5 @@
-use crate::utils::{indent_of, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::indent_of;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs
index 91585927000..635b6d83eab 100644
--- a/src/tools/clippy/clippy_lints/src/exit.rs
+++ b/src/tools/clippy/clippy_lints/src/exit.rs
@@ -1,4 +1,5 @@
-use crate::utils::{is_entrypoint_fn, match_def_path, paths, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{is_entrypoint_fn, match_def_path, paths};
 use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs
index f8038d06e50..4146b7baa10 100644
--- a/src/tools/clippy/clippy_lints/src/explicit_write.rs
+++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs
@@ -1,4 +1,5 @@
-use crate::utils::{is_expn_of, match_function_call, paths, span_lint, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::{is_expn_of, match_function_call, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
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 f466dddc13c..52a5a7acf0d 100644
--- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
+++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
@@ -1,4 +1,6 @@
-use crate::utils::{is_expn_of, is_type_diagnostic_item, match_panic_def_id, method_chain_args, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{is_expn_of, match_panic_def_id, method_chain_args};
 use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs b/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs
index c1c08597ee6..0c59db360f9 100644
--- a/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs
+++ b/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs
@@ -1,4 +1,5 @@
-use crate::utils::{match_def_path, paths, span_lint_and_then, sugg};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::{match_def_path, paths, sugg};
 use if_chain::if_chain;
 use rustc_ast::util::parser::AssocOp;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs
index 8e256f34684..1ca5c685a75 100644
--- a/src/tools/clippy/clippy_lints/src/float_literal.rs
+++ b/src/tools/clippy/clippy_lints/src/float_literal.rs
@@ -1,4 +1,5 @@
-use crate::utils::{numeric_literal, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::numeric_literal;
 use if_chain::if_chain;
 use rustc_ast::ast::{self, LitFloatType, LitKind};
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index 086a791520f..0b5f0379ce6 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -2,7 +2,8 @@ use crate::consts::{
     constant, constant_simple, Constant,
     Constant::{Int, F32, F64},
 };
-use crate::utils::{eq_expr_value, get_parent_expr, numeric_literal, span_lint_and_sugg, sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::{eq_expr_value, get_parent_expr, numeric_literal, sugg};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp};
diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs
index fd6bf19db94..a33f987b423 100644
--- a/src/tools/clippy/clippy_lints/src/format.rs
+++ b/src/tools/clippy/clippy_lints/src/format.rs
@@ -1,8 +1,8 @@
-use crate::utils::paths;
-use crate::utils::{
-    is_expn_of, is_type_diagnostic_item, last_path_segment, match_def_path, match_function_call, snippet, snippet_opt,
-    span_lint_and_then,
-};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::paths;
+use clippy_utils::source::{snippet, snippet_opt};
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{is_expn_of, last_path_segment, match_def_path, match_function_call};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs
index 1bd16e6cce5..b10e83c0ea8 100644
--- a/src/tools/clippy/clippy_lints/src/formatting.rs
+++ b/src/tools/clippy/clippy_lints/src/formatting.rs
@@ -1,4 +1,6 @@
-use crate::utils::{differing_macro_contexts, snippet_opt, span_lint_and_help, span_lint_and_note};
+use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note};
+use clippy_utils::differing_macro_contexts;
+use clippy_utils::source::snippet_opt;
 use if_chain::if_chain;
 use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp};
 use rustc_lint::{EarlyContext, EarlyLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs
index b644bb07990..e5ec245e502 100644
--- a/src/tools/clippy/clippy_lints/src/from_over_into.rs
+++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs
@@ -1,5 +1,6 @@
-use crate::utils::paths::INTO;
-use crate::utils::{match_def_path, meets_msrv, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::paths::INTO;
+use clippy_utils::{match_def_path, meets_msrv};
 use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
diff --git a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
index 0933f983014..3da5bc95b6d 100644
--- a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
+++ b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
@@ -1,3 +1,6 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::sugg::Sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{def, Expr, ExprKind, PrimTy, QPath, TyKind};
@@ -6,10 +9,6 @@ use rustc_middle::ty::Ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::sym;
 
-use crate::utils::is_type_diagnostic_item;
-use crate::utils::span_lint_and_sugg;
-use crate::utils::sugg::Sugg;
-
 declare_clippy_lint! {
     /// **What it does:**
     /// Checks for function invocations of the form `primitive::from_str_radix(s, 10)`
diff --git a/src/tools/clippy/clippy_lints/src/functions.rs b/src/tools/clippy/clippy_lints/src/functions.rs
index c474db06fe3..5fe46065348 100644
--- a/src/tools/clippy/clippy_lints/src/functions.rs
+++ b/src/tools/clippy/clippy_lints/src/functions.rs
@@ -1,7 +1,9 @@
-use crate::utils::{
-    attr_by_name, attrs::is_proc_macro, is_must_use_ty, is_trait_impl_item, is_type_diagnostic_item, iter_input_pats,
-    match_def_path, must_use_attr, path_to_local, return_ty, snippet, snippet_opt, span_lint, span_lint_and_help,
-    span_lint_and_then, trait_ref_of_method, type_is_unsafe_function,
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then};
+use clippy_utils::source::{snippet, snippet_opt};
+use clippy_utils::ty::{is_must_use_ty, is_type_diagnostic_item, type_is_unsafe_function};
+use clippy_utils::{
+    attr_by_name, attrs::is_proc_macro, is_trait_impl_item, iter_input_pats, match_def_path, must_use_attr,
+    path_to_local, return_ty, trait_ref_of_method,
 };
 use if_chain::if_chain;
 use rustc_ast::ast::Attribute;
@@ -514,7 +516,7 @@ fn check_needless_must_use(
                 );
             },
         );
-    } else if !attr.is_value_str() && is_must_use_ty(cx, return_ty(cx, item_id)) {
+    } else if !attr.value_str().is_some() && is_must_use_ty(cx, return_ty(cx, item_id)) {
         span_lint_and_help(
             cx,
             DOUBLE_MUST_USE,
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index 9e1a8864a3e..04730ace887 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -1,4 +1,5 @@
-use crate::utils;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::return_ty;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, FnDecl, HirId};
 use rustc_infer::infer::TyCtxtInferExt;
@@ -61,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
         if let FnKind::Closure = kind {
             return;
         }
-        let ret_ty = utils::return_ty(cx, hir_id);
+        let ret_ty = return_ty(cx, hir_id);
         if let Opaque(id, subst) = *ret_ty.kind() {
             let preds = cx.tcx.explicit_item_bounds(id);
             let mut is_future = false;
@@ -84,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
                     fulfillment_cx.select_all_or_error(&infcx)
                 });
                 if let Err(send_errors) = send_result {
-                    utils::span_lint_and_then(
+                    span_lint_and_then(
                         cx,
                         FUTURE_NOT_SEND,
                         span,
diff --git a/src/tools/clippy/clippy_lints/src/get_last_with_len.rs b/src/tools/clippy/clippy_lints/src/get_last_with_len.rs
index cdd8a42e7cd..cbcef567c53 100644
--- a/src/tools/clippy/clippy_lints/src/get_last_with_len.rs
+++ b/src/tools/clippy/clippy_lints/src/get_last_with_len.rs
@@ -1,6 +1,9 @@
 //! lint on using `x.get(x.len() - 1)` instead of `x.last()`
 
-use crate::utils::{is_type_diagnostic_item, snippet_with_applicability, span_lint_and_sugg, SpanlessEq};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::SpanlessEq;
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/identity_op.rs b/src/tools/clippy/clippy_lints/src/identity_op.rs
index 8501d347702..8bed5e1bf64 100644
--- a/src/tools/clippy/clippy_lints/src/identity_op.rs
+++ b/src/tools/clippy/clippy_lints/src/identity_op.rs
@@ -1,3 +1,4 @@
+use clippy_utils::source::snippet;
 use if_chain::if_chain;
 use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -6,7 +7,8 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 
 use crate::consts::{constant_simple, Constant};
-use crate::utils::{clip, snippet, span_lint, unsext};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{clip, unsext};
 
 declare_clippy_lint! {
     /// **What it does:** Checks for identity operations, e.g., `x + 0`.
diff --git a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
index 58511c6d57c..4aab43256bf 100644
--- a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
+++ b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
@@ -1,4 +1,6 @@
-use crate::utils::{is_type_diagnostic_item, span_lint_and_help, SpanlessEq};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::SpanlessEq;
 use if_chain::if_chain;
 use rustc_hir::intravisit::{self as visit, NestedVisitorMap, Visitor};
 use rustc_hir::{Expr, ExprKind, MatchSource};
diff --git a/src/tools/clippy/clippy_lints/src/if_let_some_result.rs b/src/tools/clippy/clippy_lints/src/if_let_some_result.rs
index 1194bd7e55e..6e9280c8c7e 100644
--- a/src/tools/clippy/clippy_lints/src/if_let_some_result.rs
+++ b/src/tools/clippy/clippy_lints/src/if_let_some_result.rs
@@ -1,4 +1,7 @@
-use crate::utils::{is_type_diagnostic_item, method_chain_args, snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::method_chain_args;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::is_type_diagnostic_item;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, MatchSource, PatKind, QPath};
diff --git a/src/tools/clippy/clippy_lints/src/if_not_else.rs b/src/tools/clippy/clippy_lints/src/if_not_else.rs
index b86d2e76656..c56f67df061 100644
--- a/src/tools/clippy/clippy_lints/src/if_not_else.rs
+++ b/src/tools/clippy/clippy_lints/src/if_not_else.rs
@@ -1,13 +1,12 @@
 //! lint on if branches that could be swapped so no `!` operation is necessary
 //! on the condition
 
+use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp};
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use crate::utils::span_lint_and_help;
-
 declare_clippy_lint! {
     /// **What it does:** Checks for usage of `!` or `!=` in an if condition with an
     /// else branch.
diff --git a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
new file mode 100644
index 00000000000..0b5bf060d4c
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
@@ -0,0 +1,117 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::source::snippet_with_macro_callsite;
+use clippy_utils::{match_qpath, meets_msrv, parent_node_is_if_expr};
+use if_chain::if_chain;
+use rustc_hir::{Expr, ExprKind};
+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};
+
+const IF_THEN_SOME_ELSE_NONE_MSRV: RustcVersion = RustcVersion::new(1, 50, 0);
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for if-else that could be written to `bool::then`.
+    ///
+    /// **Why is this bad?** Looks a little redundant. Using `bool::then` helps it have less lines of code.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// # let v = vec![0];
+    /// let a = if v.is_empty() {
+    ///     println!("true!");
+    ///     Some(42)
+    /// } else {
+    ///     None
+    /// };
+    /// ```
+    ///
+    /// Could be written:
+    ///
+    /// ```rust
+    /// # let v = vec![0];
+    /// let a = v.is_empty().then(|| {
+    ///     println!("true!");
+    ///     42
+    /// });
+    /// ```
+    pub IF_THEN_SOME_ELSE_NONE,
+    restriction,
+    "Finds if-else that could be written using `bool::then`"
+}
+
+pub struct IfThenSomeElseNone {
+    msrv: Option<RustcVersion>,
+}
+
+impl IfThenSomeElseNone {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        Self { msrv }
+    }
+}
+
+impl_lint_pass!(IfThenSomeElseNone => [IF_THEN_SOME_ELSE_NONE]);
+
+impl LateLintPass<'_> for IfThenSomeElseNone {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'tcx Expr<'_>) {
+        if !meets_msrv(self.msrv.as_ref(), &IF_THEN_SOME_ELSE_NONE_MSRV) {
+            return;
+        }
+
+        if in_external_macro(cx.sess(), expr.span) {
+            return;
+        }
+
+        // We only care about the top-most `if` in the chain
+        if parent_node_is_if_expr(expr, cx) {
+            return;
+        }
+
+        if_chain! {
+            if let ExprKind::If(ref cond, ref then, Some(ref els)) = expr.kind;
+            if let ExprKind::Block(ref then_block, _) = then.kind;
+            if let Some(ref then_expr) = then_block.expr;
+            if let ExprKind::Call(ref then_call, [then_arg]) = then_expr.kind;
+            if let ExprKind::Path(ref then_call_qpath) = then_call.kind;
+            if match_qpath(then_call_qpath, &clippy_utils::paths::OPTION_SOME);
+            if let ExprKind::Block(ref els_block, _) = els.kind;
+            if els_block.stmts.is_empty();
+            if let Some(ref els_expr) = els_block.expr;
+            if let ExprKind::Path(ref els_call_qpath) = els_expr.kind;
+            if match_qpath(els_call_qpath, &clippy_utils::paths::OPTION_NONE);
+            then {
+                let cond_snip = snippet_with_macro_callsite(cx, cond.span, "[condition]");
+                let cond_snip = if matches!(cond.kind, ExprKind::Unary(_, _) | ExprKind::Binary(_, _, _)) {
+                    format!("({})", cond_snip)
+                } else {
+                    cond_snip.into_owned()
+                };
+                let arg_snip = snippet_with_macro_callsite(cx, then_arg.span, "");
+                let closure_body = if then_block.stmts.is_empty() {
+                    arg_snip.into_owned()
+                } else {
+                    format!("{{ /* snippet */ {} }}", arg_snip)
+                };
+                let help = format!(
+                    "consider using `bool::then` like: `{}.then(|| {})`",
+                    cond_snip,
+                    closure_body,
+                );
+                span_lint_and_help(
+                    cx,
+                    IF_THEN_SOME_ELSE_NONE,
+                    expr.span,
+                    "this could be simplified with `bool::then`",
+                    None,
+                    &help,
+                );
+            }
+        }
+    }
+
+    extract_msrv_attr!(LateContext);
+}
diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs
index b4f814e1dcc..6863645a92d 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_return.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs
@@ -1,4 +1,6 @@
-use crate::utils::{match_panic_def_id, snippet_opt, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::match_panic_def_id;
+use clippy_utils::source::snippet_opt;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
index 16e162badb5..5207c628987 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
@@ -1,4 +1,5 @@
-use crate::utils::{in_macro, match_qpath, span_lint_and_sugg, SpanlessEq};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::{in_macro, match_qpath, SpanlessEq};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
index 48aef74e4d3..d7ca24487a8 100644
--- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
+++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
@@ -1,3 +1,6 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
 use rustc_hir::{self as hir, ExprKind};
@@ -5,13 +8,10 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::Symbol;
 
-use if_chain::if_chain;
-
-use crate::utils::{snippet, span_lint_and_sugg};
-
 declare_clippy_lint! {
-    /// **What it does:** Checks for struct constructors where the order of the field init
-    /// shorthand in the constructor is inconsistent with the order in the struct definition.
+    /// **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,
@@ -25,11 +25,11 @@ declare_clippy_lint! {
     /// let x = 1;
     /// let y = 2;
     ///
-    /// // This assertion never fails.
+    /// // This assertion never fails:
     /// assert_eq!(Foo { x, y }, Foo { y, x });
     /// ```
     ///
-    /// inconsistent order means nothing and just decreases readability and consistency.
+    /// inconsistent order can be confusing and decreases readability and consistency.
     ///
     /// **Known problems:** None.
     ///
@@ -42,6 +42,7 @@ declare_clippy_lint! {
     /// }
     /// let x = 1;
     /// let y = 2;
+    ///
     /// Foo { y, x };
     /// ```
     ///
@@ -107,7 +108,7 @@ impl LateLintPass<'_> for InconsistentStructConstructor {
                     cx,
                     INCONSISTENT_STRUCT_CONSTRUCTOR,
                     expr.span,
-                    "inconsistent struct constructor",
+                    "struct constructor field order is inconsistent with struct definition field order",
                     "try",
                     sugg,
                     Applicability::MachineApplicable,
diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
index c919ec097a2..94d39019608 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -1,7 +1,8 @@
 //! lint on indexing and slicing operations
 
 use crate::consts::{constant, Constant};
-use crate::utils::{higher, span_lint, span_lint_and_help};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::higher;
 use rustc_ast::ast::RangeLimits;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index 7040ac3191f..fb35bc1e780 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -1,9 +1,10 @@
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::ty::{implements_trait, match_type};
+use clippy_utils::{get_trait_def_id, higher, match_qpath, paths};
 use rustc_hir::{BorrowKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, match_type, paths, span_lint};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for iteration that is guaranteed to be infinite.
     ///
diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
index 005c461f105..5b2e70e3ce9 100644
--- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
@@ -1,6 +1,7 @@
 //! lint on inherent implementations
 
-use crate::utils::{in_macro, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::in_macro;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{def_id, Crate, Impl, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs
index c1f3e1d9d68..b023e13e846 100644
--- a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs
+++ b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs
@@ -1,14 +1,12 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
+use clippy_utils::{get_trait_def_id, paths, return_ty, trait_ref_of_method};
 use if_chain::if_chain;
 use rustc_hir::{ImplItem, ImplItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
 
-use crate::utils::{
-    get_trait_def_id, implements_trait, is_type_diagnostic_item, paths, return_ty, span_lint_and_help,
-    trait_ref_of_method,
-};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for the definition of inherent methods with a signature of `to_string(&self) -> String`.
     ///
diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
index 00acbd6cc3f..20f00bd51ba 100644
--- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
+++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
@@ -1,7 +1,7 @@
 //! checks for `#[inline]` on trait methods without bodies
 
-use crate::utils::span_lint_and_then;
-use crate::utils::sugg::DiagnosticBuilderExt;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sugg::DiagnosticBuilderExt;
 use rustc_ast::ast::Attribute;
 use rustc_errors::Applicability;
 use rustc_hir::{TraitFn, TraitItem, TraitItemKind};
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 260b8988d37..c4a1222b51f 100644
--- a/src/tools/clippy/clippy_lints/src/int_plus_one.rs
+++ b/src/tools/clippy/clippy_lints/src/int_plus_one.rs
@@ -1,12 +1,12 @@
 //! lint on blocks unnecessarily using >= with a + 1 or - 1
 
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_opt;
 use rustc_ast::ast::{BinOpKind, Expr, ExprKind, Lit, LitKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use crate::utils::{snippet_opt, span_lint_and_sugg};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block
     ///
diff --git a/src/tools/clippy/clippy_lints/src/integer_division.rs b/src/tools/clippy/clippy_lints/src/integer_division.rs
index 39b4605e72f..e5482f675e7 100644
--- a/src/tools/clippy/clippy_lints/src/integer_division.rs
+++ b/src/tools/clippy/clippy_lints/src/integer_division.rs
@@ -1,4 +1,4 @@
-use crate::utils::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_help;
 use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/items_after_statements.rs b/src/tools/clippy/clippy_lints/src/items_after_statements.rs
index 0927d218446..c69571f32a2 100644
--- a/src/tools/clippy/clippy_lints/src/items_after_statements.rs
+++ b/src/tools/clippy/clippy_lints/src/items_after_statements.rs
@@ -1,6 +1,6 @@
 //! lint when items are used after statements
 
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast::{Block, ItemKind, StmtKind};
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
index a76595ed089..48dc5fefe99 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -1,5 +1,5 @@
 use crate::rustc_target::abi::LayoutOf;
-use crate::utils::span_lint_and_then;
+use clippy_utils::diagnostics::span_lint_and_then;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
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 ab4cb33612d..76584dc1822 100644
--- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
+++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
@@ -1,6 +1,7 @@
 //! lint when there is a large size difference between variants on an enum
 
-use crate::utils::{snippet_opt, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet_opt;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind, VariantData};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
index 9a448ab1256..c46b98022c6 100644
--- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
@@ -1,13 +1,13 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::source::snippet;
+use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::{self, ConstKind};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 
-use if_chain::if_chain;
-
 use crate::rustc_target::abi::LayoutOf;
-use crate::utils::{snippet, span_lint_and_help};
 
 declare_clippy_lint! {
     /// **What it does:** Checks for local arrays that may be too large.
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 1e1023b2743..717f2ea84f4 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -1,7 +1,6 @@
-use crate::utils::{
-    get_item_name, get_parent_as_impl, is_allowed, snippet_with_applicability, span_lint, span_lint_and_sugg,
-    span_lint_and_then,
-};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::{get_item_name, get_parent_as_impl, is_allowed};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_data_structures::fx::FxHashSet;
diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs
index 5863eef8a26..2d7d9c9befb 100644
--- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs
+++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs
@@ -1,4 +1,6 @@
-use crate::utils::{path_to_local_id, snippet, span_lint_and_then, visitors::LocalUsedVisitor};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet;
+use clippy_utils::{path_to_local_id, visitors::LocalUsedVisitor};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs
index 7e96dfcc7da..7e3a76ded2c 100644
--- a/src/tools/clippy/clippy_lints/src/let_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs
@@ -1,3 +1,6 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::ty::{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};
@@ -5,8 +8,6 @@ use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use crate::utils::{is_must_use_func_call, is_must_use_ty, match_type, paths, span_lint_and_help};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for `let _ = <expr>`
     /// where expr is #[must_use]
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index b4c450bda5c..a99ed7656bf 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -4,6 +4,7 @@
 #![feature(box_syntax)]
 #![feature(drain_filter)]
 #![feature(in_band_lifetimes)]
+#![feature(iter_zip)]
 #![feature(once_cell)]
 #![cfg_attr(bootstrap, feature(or_patterns))]
 #![feature(rustc_private)]
@@ -42,7 +43,7 @@ extern crate rustc_target;
 extern crate rustc_trait_selection;
 extern crate rustc_typeck;
 
-use crate::utils::parse_msrv;
+use clippy_utils::parse_msrv;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_lint::LintId;
 use rustc_session::Session;
@@ -231,6 +232,7 @@ mod identity_op;
 mod if_let_mutex;
 mod if_let_some_result;
 mod if_not_else;
+mod if_then_some_else_none;
 mod implicit_return;
 mod implicit_saturating_sub;
 mod inconsistent_struct_constructor;
@@ -349,6 +351,7 @@ mod types;
 mod undropped_manually_drops;
 mod unicode;
 mod unit_return_expecting_ord;
+mod unit_types;
 mod unnamed_address;
 mod unnecessary_sort_by;
 mod unnecessary_wraps;
@@ -680,6 +683,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &if_let_mutex::IF_LET_MUTEX,
         &if_let_some_result::IF_LET_SOME_RESULT,
         &if_not_else::IF_NOT_ELSE,
+        &if_then_some_else_none::IF_THEN_SOME_ELSE_NONE,
         &implicit_return::IMPLICIT_RETURN,
         &implicit_saturating_sub::IMPLICIT_SATURATING_SUB,
         &inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR,
@@ -958,20 +962,20 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &types::BOX_VEC,
         &types::IMPLICIT_HASHER,
         &types::INVALID_UPCAST_COMPARISONS,
-        &types::LET_UNIT_VALUE,
         &types::LINKEDLIST,
         &types::OPTION_OPTION,
         &types::RC_BUFFER,
         &types::REDUNDANT_ALLOCATION,
         &types::TYPE_COMPLEXITY,
-        &types::UNIT_ARG,
-        &types::UNIT_CMP,
         &types::VEC_BOX,
         &undropped_manually_drops::UNDROPPED_MANUALLY_DROPS,
         &unicode::INVISIBLE_CHARACTERS,
         &unicode::NON_ASCII_LITERAL,
         &unicode::UNICODE_NOT_NFC,
         &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_sort_by::UNNECESSARY_SORT_BY,
@@ -1082,8 +1086,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box map_clone::MapClone);
     store.register_late_pass(|| box map_err_ignore::MapErrIgnore);
     store.register_late_pass(|| box shadow::Shadow);
-    store.register_late_pass(|| box types::LetUnitValue);
-    store.register_late_pass(|| box types::UnitCmp);
+    store.register_late_pass(|| box unit_types::UnitTypes);
     store.register_late_pass(|| box loops::Loops);
     store.register_late_pass(|| box main_recursion::MainRecursion::default());
     store.register_late_pass(|| box lifetimes::Lifetimes);
@@ -1158,7 +1161,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box useless_conversion::UselessConversion::default());
     store.register_late_pass(|| box types::ImplicitHasher);
     store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom);
-    store.register_late_pass(|| box types::UnitArg);
     store.register_late_pass(|| box double_comparison::DoubleComparisons);
     store.register_late_pass(|| box question_mark::QuestionMark);
     store.register_early_pass(|| box suspicious_operation_groupings::SuspiciousOperationGroupings);
@@ -1241,7 +1243,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box verbose_file_reads::VerboseFileReads);
     store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default());
     store.register_late_pass(|| box unnamed_address::UnnamedAddress);
-    store.register_late_pass(|| box dereference::Dereferencing);
+    store.register_late_pass(|| box dereference::Dereferencing::default());
     store.register_late_pass(|| box option_if_let_else::OptionIfLetElse);
     store.register_late_pass(|| box future_not_send::FutureNotSend);
     store.register_late_pass(|| box if_let_mutex::IfLetMutex);
@@ -1280,6 +1282,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box redundant_slicing::RedundantSlicing);
     store.register_late_pass(|| box from_str_radix_10::FromStrRadix10);
     store.register_late_pass(|| box manual_map::ManualMap);
+    store.register_late_pass(move || box if_then_some_else_none::IfThenSomeElseNone::new(msrv));
 
     store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
         LintId::of(&arithmetic::FLOAT_ARITHMETIC),
@@ -1295,6 +1298,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&exhaustive_items::EXHAUSTIVE_STRUCTS),
         LintId::of(&exit::EXIT),
         LintId::of(&float_literal::LOSSY_FLOAT_LITERAL),
+        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),
@@ -1411,11 +1415,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&trait_bounds::TYPE_REPETITION_IN_BOUNDS),
         LintId::of(&types::IMPLICIT_HASHER),
         LintId::of(&types::INVALID_UPCAST_COMPARISONS),
-        LintId::of(&types::LET_UNIT_VALUE),
         LintId::of(&types::LINKEDLIST),
         LintId::of(&types::OPTION_OPTION),
         LintId::of(&unicode::NON_ASCII_LITERAL),
         LintId::of(&unicode::UNICODE_NOT_NFC),
+        LintId::of(&unit_types::LET_UNIT_VALUE),
         LintId::of(&unnecessary_wraps::UNNECESSARY_WRAPS),
         LintId::of(&unnested_or_patterns::UNNESTED_OR_PATTERNS),
         LintId::of(&unused_self::UNUSED_SELF),
@@ -1704,12 +1708,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&types::BOX_VEC),
         LintId::of(&types::REDUNDANT_ALLOCATION),
         LintId::of(&types::TYPE_COMPLEXITY),
-        LintId::of(&types::UNIT_ARG),
-        LintId::of(&types::UNIT_CMP),
         LintId::of(&types::VEC_BOX),
         LintId::of(&undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
         LintId::of(&unicode::INVISIBLE_CHARACTERS),
         LintId::of(&unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
+        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_sort_by::UNNECESSARY_SORT_BY),
@@ -1930,8 +1934,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&transmute::TRANSMUTE_PTR_TO_REF),
         LintId::of(&types::BORROWED_BOX),
         LintId::of(&types::TYPE_COMPLEXITY),
-        LintId::of(&types::UNIT_ARG),
         LintId::of(&types::VEC_BOX),
+        LintId::of(&unit_types::UNIT_ARG),
         LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY),
         LintId::of(&unwrap::UNNECESSARY_UNWRAP),
         LintId::of(&useless_conversion::USELESS_CONVERSION),
@@ -2001,10 +2005,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&transmute::WRONG_TRANSMUTE),
         LintId::of(&transmuting_null::TRANSMUTING_NULL),
         LintId::of(&types::ABSURD_EXTREME_COMPARISONS),
-        LintId::of(&types::UNIT_CMP),
         LintId::of(&undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
         LintId::of(&unicode::INVISIBLE_CHARACTERS),
         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),
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 3ac6e6cbbef..e3b3fa21cab 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -1,4 +1,5 @@
-use crate::utils::{in_macro, span_lint, trait_ref_of_method};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{in_macro, trait_ref_of_method};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::intravisit::{
     walk_fn_decl, walk_generic_param, walk_generics, walk_item, walk_param_bound, walk_poly_trait_ref, walk_ty,
diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs
index 87a957a9bd2..54470519260 100644
--- a/src/tools/clippy/clippy_lints/src/literal_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs
@@ -1,10 +1,11 @@
 //! Lints concerned with the grouping of digits with underscores in integral or
 //! floating-point literal expressions.
 
-use crate::utils::{
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::{
     in_macro,
     numeric_literal::{NumericLiteral, Radix},
-    snippet_opt, span_lint_and_sugg,
 };
 use if_chain::if_chain;
 use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind};
@@ -12,6 +13,7 @@ use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
+use std::iter;
 
 declare_clippy_lint! {
     /// **What it does:** Warns if a long integral or floating-point constant does
@@ -348,7 +350,7 @@ impl LiteralDigitGrouping {
 
         let group_sizes: Vec<usize> = num_lit.integer.split('_').map(str::len).collect();
         if UUID_GROUP_LENS.len() == group_sizes.len() {
-            UUID_GROUP_LENS.iter().zip(&group_sizes).all(|(&a, &b)| a == b)
+            iter::zip(&UUID_GROUP_LENS, &group_sizes).all(|(&a, &b)| a == b)
         } else {
             false
         }
diff --git a/src/tools/clippy/clippy_lints/src/loops/empty_loop.rs b/src/tools/clippy/clippy_lints/src/loops/empty_loop.rs
index 43e85538f28..dda09fecdf9 100644
--- a/src/tools/clippy/clippy_lints/src/loops/empty_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/empty_loop.rs
@@ -1,5 +1,6 @@
 use super::EMPTY_LOOP;
-use crate::utils::{is_in_panic_handler, is_no_std_crate, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::{is_in_panic_handler, is_no_std_crate};
 
 use rustc_hir::{Block, Expr};
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
index 8d98b940c66..f14dbb1d642 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
@@ -1,7 +1,9 @@
 use super::{
     get_span_of_entire_for_loop, make_iterator_snippet, IncrementVisitor, InitializeVisitor, EXPLICIT_COUNTER_LOOP,
 };
-use crate::utils::{get_enclosing_block, is_integer_const, snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::{get_enclosing_block, is_integer_const};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_block, walk_expr};
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs
index 1d778205a2a..4871a031187 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs
@@ -1,5 +1,6 @@
 use super::EXPLICIT_INTO_ITER_LOOP;
-use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
index 9683e59a396..92aa2beb66d 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
@@ -1,13 +1,14 @@
 use super::EXPLICIT_ITER_LOOP;
-use crate::utils::{match_trait_method, snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::{is_type_diagnostic_item, match_type};
+use clippy_utils::{match_trait_method, paths};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Mutability};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty, TyS};
 use rustc_span::sym;
 
-use crate::utils::{is_type_diagnostic_item, match_type, paths};
-
 pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], arg: &Expr<'_>, method_name: &str) {
     let should_lint = match method_name {
         "iter" | "iter_mut" => is_ref_iterable_type(cx, &args[0]),
diff --git a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
index 6ee9b95a3b6..8f18f54119b 100644
--- a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
@@ -1,6 +1,9 @@
 use super::FOR_KV_MAP;
-use crate::utils::visitors::LocalUsedVisitor;
-use crate::utils::{is_type_diagnostic_item, match_type, multispan_sugg, paths, snippet, span_lint_and_then, sugg};
+use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
+use clippy_utils::source::snippet;
+use clippy_utils::ty::{is_type_diagnostic_item, match_type};
+use clippy_utils::visitors::LocalUsedVisitor;
+use clippy_utils::{paths, sugg};
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
diff --git a/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs b/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs
index db22d90a304..d49b0517dcf 100644
--- a/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs
@@ -1,5 +1,7 @@
 use super::FOR_LOOPS_OVER_FALLIBLES;
-use crate::utils::{is_type_diagnostic_item, snippet, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_hir::{Expr, Pat};
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
diff --git a/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs b/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs
index cf78bbc49a3..9148fbfd497 100644
--- a/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs
@@ -1,10 +1,12 @@
 use super::ITER_NEXT_LOOP;
-use crate::utils::{match_trait_method, paths, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::is_trait_method;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
+use rustc_span::sym;
 
 pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, expr: &Expr<'_>) -> bool {
-    if match_trait_method(cx, arg, &paths::ITERATOR) {
+    if is_trait_method(cx, arg, sym::Iterator) {
         span_lint(
             cx,
             ITER_NEXT_LOOP,
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
index 3d3ae6f3152..8d2b9cccba4 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
@@ -1,10 +1,12 @@
 use super::utils::make_iterator_snippet;
 use super::MANUAL_FLATTEN;
-use crate::utils::{is_ok_ctor, is_some_ctor, path_to_local_id, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::{is_ok_ctor, is_some_ctor, path_to_local_id};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, StmtKind};
 use rustc_lint::LateContext;
+use rustc_middle::ty;
 use rustc_span::source_map::Span;
 
 /// Check for unnecessary `if let` usage in a for loop where only the `Some` or `Ok` variant of the
@@ -53,6 +55,13 @@ pub(super) fn check<'tcx>(
                 // Prepare the help message
                 let mut applicability = Applicability::MaybeIncorrect;
                 let arg_snippet = make_iterator_snippet(cx, arg, &mut applicability);
+                let copied = match cx.typeck_results().expr_ty(match_expr).kind() {
+                    ty::Ref(_, inner, _) => match inner.kind() {
+                        ty::Ref(..) => ".copied()",
+                        _ => ""
+                    }
+                    _ => ""
+                };
 
                 span_lint_and_then(
                     cx,
@@ -60,7 +69,7 @@ pub(super) fn check<'tcx>(
                     span,
                     &msg,
                     |diag| {
-                        let sugg = format!("{}.flatten()", arg_snippet);
+                        let sugg = format!("{}{}.flatten()", arg_snippet, copied);
                         diag.span_suggestion(
                             arg.span,
                             "try",
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
index 11660a8fe0d..f5758b68f60 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
@@ -1,8 +1,9 @@
 use super::{get_span_of_entire_for_loop, IncrementVisitor, InitializeVisitor, MANUAL_MEMCPY};
-use crate::utils::sugg::Sugg;
-use crate::utils::{
-    get_enclosing_block, higher, is_type_diagnostic_item, path_to_local, snippet, span_lint_and_sugg, sugg,
-};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::sugg::Sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{get_enclosing_block, higher, path_to_local, sugg};
 use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index 2a372c6307e..20291491998 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -18,7 +18,7 @@ mod while_immutable_condition;
 mod while_let_loop;
 mod while_let_on_iterator;
 
-use crate::utils::higher;
+use clippy_utils::higher;
 use rustc_hir::{Expr, ExprKind, LoopSource, Pat};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
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 cb56512db60..1425d50f560 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
@@ -1,11 +1,11 @@
 use super::MUT_RANGE_BOUND;
-use crate::utils::{higher, path_to_local, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{higher, path_to_local};
 use if_chain::if_chain;
 use rustc_hir::{BindingAnnotation, Expr, HirId, Node, PatKind};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
-use rustc_middle::mir::FakeReadCause;
-use rustc_middle::ty;
+use rustc_middle::{mir::FakeReadCause, ty};
 use rustc_span::source_map::Span;
 use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
@@ -108,7 +108,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
         }
     }
 
-    fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _:HirId) { }
+    fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) {}
 }
 
 impl MutatePairDelegate<'_, '_> {
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
index 92560c80629..5594fc7b046 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
@@ -1,9 +1,9 @@
 use super::NEEDLESS_COLLECT;
-use crate::utils::sugg::Sugg;
-use crate::utils::{
-    is_type_diagnostic_item, match_trait_method, match_type, path_to_local_id, paths, snippet, span_lint_and_sugg,
-    span_lint_and_then,
-};
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::source::snippet;
+use clippy_utils::sugg::Sugg;
+use clippy_utils::ty::{is_type_diagnostic_item, match_type};
+use clippy_utils::{is_trait_method, path_to_local_id, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_block, walk_expr, NestedVisitorMap, Visitor};
@@ -23,7 +23,7 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont
     if_chain! {
         if let ExprKind::MethodCall(ref method, _, ref args, _) = expr.kind;
         if let ExprKind::MethodCall(ref chain_method, _, _, _) = args[0].kind;
-        if chain_method.ident.name == sym!(collect) && match_trait_method(cx, &args[0], &paths::ITERATOR);
+        if chain_method.ident.name == sym!(collect) && is_trait_method(cx, &args[0], sym::Iterator);
         if let Some(ref generic_args) = chain_method.args;
         if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0);
         then {
@@ -94,7 +94,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
                     init: Some(ref init_expr), .. }
                 ) = stmt.kind;
                 if let ExprKind::MethodCall(ref method_name, _, &[ref iter_source], ..) = init_expr.kind;
-                if method_name.ident.name == sym!(collect) && match_trait_method(cx, &init_expr, &paths::ITERATOR);
+                if method_name.ident.name == sym!(collect) && is_trait_method(cx, &init_expr, sym::Iterator);
                 if let Some(ref generic_args) = method_name.args;
                 if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0);
                 if let ty = cx.typeck_results().node_type(ty.hir_id);
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
index 5f02e4b9d87..64ab3b6bfec 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
@@ -1,8 +1,10 @@
 use super::NEEDLESS_RANGE_LOOP;
-use crate::utils::visitors::LocalUsedVisitor;
-use crate::utils::{
-    contains_name, has_iter_method, higher, is_integer_const, match_trait_method, multispan_sugg, path_to_local_id,
-    paths, snippet, span_lint_and_then, sugg, SpanlessEq,
+use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
+use clippy_utils::source::snippet;
+use clippy_utils::ty::has_iter_method;
+use clippy_utils::visitors::LocalUsedVisitor;
+use clippy_utils::{
+    contains_name, higher, is_integer_const, match_trait_method, path_to_local_id, paths, sugg, SpanlessEq,
 };
 use if_chain::if_chain;
 use rustc_ast::ast;
@@ -15,7 +17,7 @@ use rustc_middle::hir::map::Map;
 use rustc_middle::middle::region;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::{sym, Symbol};
-use std::iter::Iterator;
+use std::iter::{self, Iterator};
 use std::mem;
 
 /// Checks for looping over a range and then indexing a sequence with it.
@@ -367,7 +369,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
             },
             ExprKind::MethodCall(_, _, args, _) => {
                 let def_id = self.cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
-                for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) {
+                for (ty, expr) in iter::zip(self.cx.tcx.fn_sig(def_id).inputs().skip_binder(), args) {
                     self.prefer_mutable = false;
                     if let ty::Ref(_, _, mutbl) = *ty.kind() {
                         if mutbl == Mutability::Mut {
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 45e1001d755..f63a3761a0d 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -1,5 +1,5 @@
 use super::NEVER_LOOP;
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use rustc_hir::{Block, Expr, ExprKind, HirId, InlineAsmOperand, Stmt, StmtKind};
 use rustc_lint::LateContext;
 use std::iter::{once, Iterator};
@@ -78,7 +78,7 @@ fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<&'tcx Expr<'tcx>> {
     match stmt.kind {
         StmtKind::Semi(ref e, ..) | StmtKind::Expr(ref e, ..) => Some(e),
         StmtKind::Local(ref local) => local.init.as_deref(),
-        _ => None,
+        StmtKind::Item(..) => None,
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
index f3585830e4a..849d7ec718c 100644
--- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
@@ -1,5 +1,7 @@
 use super::SAME_ITEM_PUSH;
-use crate::utils::{implements_trait, is_type_diagnostic_item, snippet_with_macro_callsite, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::source::snippet_with_macro_callsite;
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use if_chain::if_chain;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
index 38400c93c9a..8451c1c6130 100644
--- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
@@ -1,5 +1,7 @@
 use super::{get_span_of_entire_for_loop, SINGLE_ELEMENT_LOOP};
-use crate::utils::{indent_of, single_segment_path, snippet, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::single_segment_path;
+use clippy_utils::source::{indent_of, snippet};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind};
diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs
index 9e38e17719a..bb409c48532 100644
--- a/src/tools/clippy/clippy_lints/src/loops/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs
@@ -1,7 +1,5 @@
-use crate::utils::{
-    get_parent_expr, get_trait_def_id, has_iter_method, implements_trait, is_integer_const, path_to_local,
-    path_to_local_id, paths, sugg,
-};
+use clippy_utils::ty::{has_iter_method, implements_trait};
+use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_local_id, sugg};
 use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
@@ -10,7 +8,7 @@ use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, P
 use rustc_lint::LateContext;
 use rustc_middle::hir::map::Map;
 use rustc_span::source_map::Span;
-use rustc_span::symbol::Symbol;
+use rustc_span::symbol::{sym, Symbol};
 use std::iter::Iterator;
 
 #[derive(Debug, PartialEq)]
@@ -316,7 +314,7 @@ pub(super) fn get_span_of_entire_for_loop(expr: &Expr<'_>) -> Span {
 /// If `arg` was the argument to a `for` loop, return the "cleanest" way of writing the
 /// actual `Iterator` that the loop uses.
 pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic_ref: &mut Applicability) -> String {
-    let impls_iterator = get_trait_def_id(cx, &paths::ITERATOR).map_or(false, |id| {
+    let impls_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| {
         implements_trait(cx, cx.typeck_results().expr_ty(arg), id, &[])
     });
     if impls_iterator {
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
index 05e0a722563..cad9ff8489a 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
@@ -1,7 +1,7 @@
 use super::WHILE_IMMUTABLE_CONDITION;
 use crate::consts::constant;
-use crate::utils::span_lint_and_then;
-use crate::utils::usage::mutated_variables;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::usage::mutated_variables;
 use if_chain::if_chain;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def::{DefKind, Res};
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
index 65d8f2f1111..ffe8c0c5494 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
@@ -1,5 +1,6 @@
 use super::WHILE_LET_LOOP;
-use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
 use rustc_errors::Applicability;
 use rustc_hir::{Block, Expr, ExprKind, MatchSource, StmtKind};
 use rustc_lint::{LateContext, LintContext};
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
index e5a47694faa..57fc6250a9a 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
@@ -1,9 +1,11 @@
 use super::utils::{LoopNestVisitor, Nesting};
 use super::WHILE_LET_ON_ITERATOR;
-use crate::utils::usage::mutated_variables;
-use crate::utils::{
-    get_enclosing_block, get_trait_def_id, implements_trait, is_refutable, last_path_segment, match_trait_method,
-    path_to_local, path_to_local_id, paths, snippet_with_applicability, span_lint_and_sugg,
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::implements_trait;
+use clippy_utils::usage::mutated_variables;
+use clippy_utils::{
+    get_enclosing_block, is_refutable, is_trait_method, last_path_segment, path_to_local, path_to_local_id,
 };
 use if_chain::if_chain;
 use rustc_errors::Applicability;
@@ -11,7 +13,6 @@ use rustc_hir::intravisit::{walk_block, walk_expr, NestedVisitorMap, Visitor};
 use rustc_hir::{Expr, ExprKind, HirId, MatchSource, Node, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::hir::map::Map;
-
 use rustc_span::symbol::sym;
 
 pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
@@ -27,7 +28,7 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             // Don't lint when the iterator is recreated on every iteration
             if_chain! {
                 if let ExprKind::MethodCall(..) | ExprKind::Call(..) = iter_expr.kind;
-                if let Some(iter_def_id) = get_trait_def_id(cx, &paths::ITERATOR);
+                if let Some(iter_def_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
                 if implements_trait(cx, cx.typeck_results().expr_ty(iter_expr), iter_def_id, &[]);
                 then {
                     return;
@@ -36,7 +37,7 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 
             let lhs_constructor = last_path_segment(qpath);
             if method_path.ident.name == sym::next
-                && match_trait_method(cx, match_expr, &paths::ITERATOR)
+                && is_trait_method(cx, match_expr, sym::Iterator)
                 && lhs_constructor.ident.name == sym::Some
                 && (pat_args.is_empty()
                     || !is_refutable(cx, &pat_args[0])
diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs
index 6d9c78393c8..d573c297838 100644
--- a/src/tools/clippy/clippy_lints/src/macro_use.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_use.rs
@@ -1,4 +1,6 @@
-use crate::utils::{in_macro, snippet, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::in_macro;
+use clippy_utils::source::snippet;
 use hir::def::{DefKind, Res};
 use if_chain::if_chain;
 use rustc_ast::ast;
diff --git a/src/tools/clippy/clippy_lints/src/main_recursion.rs b/src/tools/clippy/clippy_lints/src/main_recursion.rs
index 1b274c79d38..07d8a440aea 100644
--- a/src/tools/clippy/clippy_lints/src/main_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/main_recursion.rs
@@ -1,10 +1,11 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::source::snippet;
+use clippy_utils::{is_entrypoint_fn, is_no_std_crate};
+use if_chain::if_chain;
 use rustc_hir::{Crate, Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 
-use crate::utils::{is_entrypoint_fn, is_no_std_crate, snippet, span_lint_and_help};
-use if_chain::if_chain;
-
 declare_clippy_lint! {
     /// **What it does:** Checks for recursion using the entrypoint.
     ///
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 2e2e693592c..5d88ff3b99f 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -1,5 +1,7 @@
-use crate::utils::paths::FUTURE_FROM_GENERATOR;
-use crate::utils::{match_function_call, position_before_rarrow, snippet_block, snippet_opt, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::match_function_call;
+use clippy_utils::paths::FUTURE_FROM_GENERATOR;
+use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
diff --git a/src/tools/clippy/clippy_lints/src/manual_map.rs b/src/tools/clippy/clippy_lints/src/manual_map.rs
index ac1d51e1993..ed157783b72 100644
--- a/src/tools/clippy/clippy_lints/src/manual_map.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_map.rs
@@ -1,18 +1,14 @@
-use crate::{
-    map_unit_fn::OPTION_MAP_UNIT_FN,
-    matches::MATCH_AS_REF,
-    utils::{
-        can_partially_move_ty, is_allowed, is_type_diagnostic_item, match_def_path, match_var, paths,
-        peel_hir_expr_refs, peel_mid_ty_refs_is_mutable, snippet_with_applicability, snippet_with_context,
-        span_lint_and_sugg,
-    },
-};
+use crate::{map_unit_fn::OPTION_MAP_UNIT_FN, matches::MATCH_AS_REF};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
+use clippy_utils::ty::{can_partially_move_ty, is_type_diagnostic_item, peel_mid_ty_refs_is_mutable};
+use clippy_utils::{is_allowed, is_else_clause_of_if_let_else, match_def_path, match_var, paths, peel_hir_expr_refs};
 use rustc_ast::util::parser::PREC_POSTFIX;
 use rustc_errors::Applicability;
 use rustc_hir::{
     def::Res,
     intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor},
-    Arm, BindingAnnotation, Block, Expr, ExprKind, Mutability, Pat, PatKind, Path, QPath,
+    Arm, BindingAnnotation, Block, Expr, ExprKind, MatchSource, Mutability, Pat, PatKind, Path, QPath,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
@@ -55,8 +51,11 @@ impl LateLintPass<'_> for ManualMap {
             return;
         }
 
-        if let ExprKind::Match(scrutinee, [arm1 @ Arm { guard: None, .. }, arm2 @ Arm { guard: None, .. }], _) =
-            expr.kind
+        if let ExprKind::Match(
+            scrutinee,
+            [arm1 @ Arm { guard: None, .. }, arm2 @ Arm { guard: None, .. }],
+            match_kind,
+        ) = expr.kind
         {
             let (scrutinee_ty, ty_ref_count, ty_mutability) =
                 peel_mid_ty_refs_is_mutable(cx.typeck_results().expr_ty(scrutinee));
@@ -129,7 +128,7 @@ impl LateLintPass<'_> for ManualMap {
             // Remove address-of expressions from the scrutinee. Either `as_ref` will be called, or
             // it's being passed by value.
             let scrutinee = peel_hir_expr_refs(scrutinee).0;
-            let scrutinee_str = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
+            let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
             let scrutinee_str =
                 if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX {
                     format!("({})", scrutinee_str)
@@ -160,7 +159,7 @@ impl LateLintPass<'_> for ManualMap {
                             "|{}{}| {}",
                             annotation,
                             some_binding,
-                            snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app)
+                            snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app).0
                         )
                     },
                 }
@@ -168,8 +167,8 @@ impl LateLintPass<'_> for ManualMap {
                 // TODO: handle explicit reference annotations.
                 format!(
                     "|{}| {}",
-                    snippet_with_context(cx, some_pat.span, expr_ctxt, "..", &mut app),
-                    snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app)
+                    snippet_with_context(cx, some_pat.span, expr_ctxt, "..", &mut app).0,
+                    snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app).0
                 )
             } else {
                 // Refutable bindings and mixed reference annotations can't be handled by `map`.
@@ -182,7 +181,12 @@ impl LateLintPass<'_> for ManualMap {
                 expr.span,
                 "manual implementation of `Option::map`",
                 "try this",
-                format!("{}{}.map({})", scrutinee_str, as_ref_str, body_str),
+                if matches!(match_kind, MatchSource::IfLetDesugar { .. }) && is_else_clause_of_if_let_else(cx.tcx, expr)
+                {
+                    format!("{{ {}{}.map({}) }}", scrutinee_str, as_ref_str, body_str)
+                } else {
+                    format!("{}{}.map({})", scrutinee_str, as_ref_str, body_str)
+                },
                 app,
             );
         }
diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
index 7e6d4d3a216..95261580b8e 100644
--- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
@@ -1,6 +1,8 @@
-use crate::utils::{meets_msrv, snippet_opt, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::meets_msrv;
+use clippy_utils::source::snippet_opt;
 use if_chain::if_chain;
-use rustc_ast::ast::{Attribute, Item, ItemKind, FieldDef, Variant, VariantData, VisibilityKind};
+use rustc_ast::ast::{Attribute, FieldDef, Item, ItemKind, Variant, VariantData, VisibilityKind};
 use rustc_attr as attr;
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/manual_ok_or.rs b/src/tools/clippy/clippy_lints/src/manual_ok_or.rs
index efb05b8ffdf..9bfae602c40 100644
--- a/src/tools/clippy/clippy_lints/src/manual_ok_or.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_ok_or.rs
@@ -1,7 +1,7 @@
-use crate::utils::{
-    indent_of, is_type_diagnostic_item, match_qpath, path_to_local_id, paths, reindent_multiline, snippet_opt,
-    span_lint_and_sugg,
-};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{match_qpath, path_to_local_id, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, PatKind};
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 42a92104a49..9da37efddac 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -1,9 +1,8 @@
 use crate::consts::{constant, Constant};
-use crate::utils::usage::mutated_variables;
-use crate::utils::{
-    eq_expr_value, higher, match_def_path, meets_msrv, multispan_sugg, paths, snippet, span_lint_and_then,
-};
-
+use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
+use clippy_utils::source::snippet;
+use clippy_utils::usage::mutated_variables;
+use clippy_utils::{eq_expr_value, higher, match_def_path, meets_msrv, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_hir::def::Res;
diff --git a/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs
index b452225b5db..f296d6a1a15 100644
--- a/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs
@@ -1,6 +1,9 @@
 use crate::consts::constant_simple;
-use crate::utils;
-use crate::utils::{path_to_local_id, sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::usage::contains_return_break_continue_macro;
+use clippy_utils::{in_constant, match_qpath, path_to_local_id, paths, sugg};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Arm, Expr, ExprKind, Pat, PatKind};
@@ -42,7 +45,7 @@ declare_lint_pass!(ManualUnwrapOr => [MANUAL_UNWRAP_OR]);
 
 impl LateLintPass<'_> for ManualUnwrapOr {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if in_external_macro(cx.sess(), expr.span) {
+        if in_external_macro(cx.sess(), expr.span) || in_constant(cx, expr.hir_id) {
             return;
         }
         lint_manual_unwrap_or(cx, expr);
@@ -72,19 +75,19 @@ fn lint_manual_unwrap_or<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
             if let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)|
                 match arm.pat.kind {
                     PatKind::Path(ref some_qpath) =>
-                        utils::match_qpath(some_qpath, &utils::paths::OPTION_NONE),
+                        match_qpath(some_qpath, &paths::OPTION_NONE),
                     PatKind::TupleStruct(ref err_qpath, &[Pat { kind: PatKind::Wild, .. }], _) =>
-                        utils::match_qpath(err_qpath, &utils::paths::RESULT_ERR),
+                        match_qpath(err_qpath, &paths::RESULT_ERR),
                     _ => false,
                 }
             );
             let unwrap_arm = &arms[1 - idx];
             if let PatKind::TupleStruct(ref unwrap_qpath, &[unwrap_pat], _) = unwrap_arm.pat.kind;
-            if utils::match_qpath(unwrap_qpath, &utils::paths::OPTION_SOME)
-                || utils::match_qpath(unwrap_qpath, &utils::paths::RESULT_OK);
+            if match_qpath(unwrap_qpath, &paths::OPTION_SOME)
+                || match_qpath(unwrap_qpath, &paths::RESULT_OK);
             if let PatKind::Binding(_, binding_hir_id, ..) = unwrap_pat.kind;
             if path_to_local_id(unwrap_arm.body, binding_hir_id);
-            if !utils::usage::contains_return_break_continue_macro(or_arm.body);
+            if !contains_return_break_continue_macro(or_arm.body);
             then {
                 Some(or_arm)
             } else {
@@ -96,21 +99,21 @@ fn lint_manual_unwrap_or<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
     if_chain! {
         if let ExprKind::Match(scrutinee, match_arms, _) = expr.kind;
         let ty = cx.typeck_results().expr_ty(scrutinee);
-        if let Some(case) = if utils::is_type_diagnostic_item(cx, ty, sym::option_type) {
+        if let Some(case) = if is_type_diagnostic_item(cx, ty, sym::option_type) {
             Some(Case::Option)
-        } else if utils::is_type_diagnostic_item(cx, ty, sym::result_type) {
+        } else if is_type_diagnostic_item(cx, ty, sym::result_type) {
             Some(Case::Result)
         } else {
             None
         };
         if let Some(or_arm) = applicable_or_arm(match_arms);
-        if let Some(or_body_snippet) = utils::snippet_opt(cx, or_arm.body.span);
-        if let Some(indent) = utils::indent_of(cx, expr.span);
+        if let Some(or_body_snippet) = snippet_opt(cx, or_arm.body.span);
+        if let Some(indent) = indent_of(cx, expr.span);
         if constant_simple(cx, cx.typeck_results(), or_arm.body).is_some();
         then {
             let reindented_or_body =
-                utils::reindent_multiline(or_body_snippet.into(), true, Some(indent));
-            utils::span_lint_and_sugg(
+                reindent_multiline(or_body_snippet.into(), true, Some(indent));
+            span_lint_and_sugg(
                 cx,
                 MANUAL_UNWRAP_OR, expr.span,
                 &format!("this pattern reimplements `{}`", case.unwrap_fn_path()),
diff --git a/src/tools/clippy/clippy_lints/src/map_clone.rs b/src/tools/clippy/clippy_lints/src/map_clone.rs
index 4b685c09a05..cfcc705eabc 100644
--- a/src/tools/clippy/clippy_lints/src/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/map_clone.rs
@@ -1,7 +1,8 @@
-use crate::utils::paths;
-use crate::utils::{
-    is_copy, is_type_diagnostic_item, match_trait_method, remove_blocks, snippet_with_applicability, span_lint_and_sugg,
-};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_trait_method;
+use clippy_utils::remove_blocks;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::{is_copy, is_type_diagnostic_item};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -55,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
             if args.len() == 2;
             if method.ident.name == sym::map;
             let ty = cx.typeck_results().expr_ty(&args[0]);
-            if is_type_diagnostic_item(cx, ty, sym::option_type) || match_trait_method(cx, e, &paths::ITERATOR);
+            if is_type_diagnostic_item(cx, ty, sym::option_type) || is_trait_method(cx, e, sym::Iterator);
             if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].kind;
             let closure_body = cx.tcx.hir().body(body_id);
             let closure_expr = remove_blocks(&closure_body.value);
diff --git a/src/tools/clippy/clippy_lints/src/map_err_ignore.rs b/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
index 76fe8e776ea..a6a63961be5 100644
--- a/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
+++ b/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
@@ -1,5 +1,4 @@
-use crate::utils::span_lint_and_help;
-
+use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_hir::{CaptureBy, Expr, ExprKind, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/map_identity.rs b/src/tools/clippy/clippy_lints/src/map_identity.rs
index 9f9c108a85a..75191e1f9ee 100644
--- a/src/tools/clippy/clippy_lints/src/map_identity.rs
+++ b/src/tools/clippy/clippy_lints/src/map_identity.rs
@@ -1,7 +1,6 @@
-use crate::utils::{
-    is_adjusted, is_type_diagnostic_item, match_path, match_trait_method, match_var, paths, remove_blocks,
-    span_lint_and_sugg,
-};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{is_adjusted, is_trait_method, match_path, match_var, paths, remove_blocks};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Body, Expr, ExprKind, Pat, PatKind, QPath, StmtKind};
@@ -65,7 +64,7 @@ fn get_map_argument<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a
         if let ExprKind::MethodCall(ref method, _, ref args, _) = expr.kind;
         if args.len() == 2 && method.ident.name == sym::map;
         let caller_ty = cx.typeck_results().expr_ty(&args[0]);
-        if match_trait_method(cx, expr, &paths::ITERATOR)
+        if is_trait_method(cx, expr, sym::Iterator)
             || is_type_diagnostic_item(cx, caller_ty, sym::result_type)
             || is_type_diagnostic_item(cx, caller_ty, sym::option_type);
         then {
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 01126e86199..d4764b5ccff 100644
--- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
@@ -1,4 +1,7 @@
-use crate::utils::{is_type_diagnostic_item, iter_input_pats, method_chain_args, snippet, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{iter_input_pats, method_chain_args};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
diff --git a/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs b/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs
index 086dae9422f..ccaa5e98c83 100644
--- a/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs
+++ b/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs
@@ -1,4 +1,6 @@
-use crate::utils::{is_type_diagnostic_item, is_type_lang_item, snippet, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem, MatchSource};
diff --git a/src/tools/clippy/clippy_lints/src/matches.rs b/src/tools/clippy/clippy_lints/src/matches.rs
index 8570cd724b2..2f2dc4cfc6b 100644
--- a/src/tools/clippy/clippy_lints/src/matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches.rs
@@ -1,32 +1,35 @@
 use crate::consts::{constant, miri_to_const, Constant};
-use crate::utils::sugg::Sugg;
-use crate::utils::visitors::LocalUsedVisitor;
-use crate::utils::{
-    expr_block, get_parent_expr, implements_trait, in_macro, indent_of, is_allowed, is_expn_of, is_refutable,
-    is_type_diagnostic_item, is_wild, match_qpath, match_type, meets_msrv, multispan_sugg, path_to_local,
-    path_to_local_id, peel_hir_pat_refs, peel_mid_ty_refs, peel_n_hir_expr_refs, remove_blocks, snippet, snippet_block,
-    snippet_opt, snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg,
-    span_lint_and_then, strip_pat_refs,
+use clippy_utils::diagnostics::{
+    multispan_sugg, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
 };
-use crate::utils::{paths, search_same, SpanlessEq, SpanlessHash};
+use clippy_utils::source::{expr_block, indent_of, snippet, snippet_block, snippet_opt, snippet_with_applicability};
+use clippy_utils::sugg::Sugg;
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, match_type, peel_mid_ty_refs};
+use clippy_utils::visitors::LocalUsedVisitor;
+use clippy_utils::{
+    get_parent_expr, in_macro, is_allowed, is_expn_of, is_refutable, is_wild, match_qpath, meets_msrv, path_to_local,
+    path_to_local_id, peel_hir_pat_refs, peel_n_hir_expr_refs, recurse_or_patterns, remove_blocks, strip_pat_refs,
+};
+use clippy_utils::{paths, search_same, SpanlessEq, SpanlessHash};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
-use rustc_hir::def::CtorKind;
+use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::{
-    Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Guard, HirId, Local, MatchSource, Mutability, Node, Pat,
-    PatKind, QPath, RangeEnd,
+    self as hir, Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Guard, HirId, Local, MatchSource,
+    Mutability, Node, Pat, PatKind, PathSegment, QPath, RangeEnd, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, Ty, TyS};
+use rustc_middle::ty::{self, Ty, TyS, VariantDef};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::{Span, Spanned};
 use rustc_span::sym;
 use std::cmp::Ordering;
 use std::collections::hash_map::Entry;
+use std::iter;
 use std::ops::Bound;
 
 declare_clippy_lint! {
@@ -954,114 +957,181 @@ fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm
     }
 }
 
-fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
-    let ty = cx.typeck_results().expr_ty(ex);
-    if !ty.is_enum() {
-        // If there isn't a nice closed set of possible values that can be conveniently enumerated,
-        // don't complain about not enumerating the mall.
-        return;
+enum CommonPrefixSearcher<'a> {
+    None,
+    Path(&'a [PathSegment<'a>]),
+    Mixed,
+}
+impl CommonPrefixSearcher<'a> {
+    fn with_path(&mut self, path: &'a [PathSegment<'a>]) {
+        match path {
+            [path @ .., _] => self.with_prefix(path),
+            [] => (),
+        }
     }
 
+    fn with_prefix(&mut self, path: &'a [PathSegment<'a>]) {
+        match self {
+            Self::None => *self = Self::Path(path),
+            Self::Path(self_path)
+                if path
+                    .iter()
+                    .map(|p| p.ident.name)
+                    .eq(self_path.iter().map(|p| p.ident.name)) => {},
+            Self::Path(_) => *self = Self::Mixed,
+            Self::Mixed => (),
+        }
+    }
+}
+
+#[allow(clippy::too_many_lines)]
+fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
+    let ty = cx.typeck_results().expr_ty(ex).peel_refs();
+    let adt_def = match ty.kind() {
+        ty::Adt(adt_def, _)
+            if adt_def.is_enum()
+                && !(is_type_diagnostic_item(cx, ty, sym::option_type)
+                    || is_type_diagnostic_item(cx, ty, sym::result_type)) =>
+        {
+            adt_def
+        },
+        _ => return,
+    };
+
     // First pass - check for violation, but don't do much book-keeping because this is hopefully
     // the uncommon case, and the book-keeping is slightly expensive.
     let mut wildcard_span = None;
     let mut wildcard_ident = None;
+    let mut has_non_wild = false;
     for arm in arms {
-        if let PatKind::Wild = arm.pat.kind {
-            wildcard_span = Some(arm.pat.span);
-        } else if let PatKind::Binding(_, _, ident, None) = arm.pat.kind {
-            wildcard_span = Some(arm.pat.span);
-            wildcard_ident = Some(ident);
+        match peel_hir_pat_refs(arm.pat).0.kind {
+            PatKind::Wild => wildcard_span = Some(arm.pat.span),
+            PatKind::Binding(_, _, ident, None) => {
+                wildcard_span = Some(arm.pat.span);
+                wildcard_ident = Some(ident);
+            },
+            _ => has_non_wild = true,
         }
     }
+    let wildcard_span = match wildcard_span {
+        Some(x) if has_non_wild => x,
+        _ => return,
+    };
 
-    if let Some(wildcard_span) = wildcard_span {
-        // Accumulate the variants which should be put in place of the wildcard because they're not
-        // already covered.
+    // Accumulate the variants which should be put in place of the wildcard because they're not
+    // already covered.
+    let mut missing_variants: Vec<_> = adt_def.variants.iter().collect();
 
-        let mut missing_variants = vec![];
-        if let ty::Adt(def, _) = ty.kind() {
-            for variant in &def.variants {
-                missing_variants.push(variant);
+    let mut path_prefix = CommonPrefixSearcher::None;
+    for arm in arms {
+        // Guards mean that this case probably isn't exhaustively covered. Technically
+        // this is incorrect, as we should really check whether each variant is exhaustively
+        // covered by the set of guards that cover it, but that's really hard to do.
+        recurse_or_patterns(arm.pat, |pat| {
+            let path = match &peel_hir_pat_refs(pat).0.kind {
+                PatKind::Path(path) => {
+                    #[allow(clippy::match_same_arms)]
+                    let id = match cx.qpath_res(path, pat.hir_id) {
+                        Res::Def(DefKind::Const | DefKind::ConstParam | DefKind::AnonConst, _) => return,
+                        Res::Def(_, id) => id,
+                        _ => return,
+                    };
+                    if arm.guard.is_none() {
+                        missing_variants.retain(|e| e.ctor_def_id != Some(id));
+                    }
+                    path
+                },
+                PatKind::TupleStruct(path, patterns, ..) => {
+                    if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p)) {
+                        let id = cx.qpath_res(path, pat.hir_id).def_id();
+                        missing_variants.retain(|e| e.ctor_def_id != Some(id));
+                    }
+                    path
+                },
+                PatKind::Struct(path, patterns, ..) => {
+                    if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p.pat)) {
+                        let id = cx.qpath_res(path, pat.hir_id).def_id();
+                        missing_variants.retain(|e| e.def_id != id);
+                    }
+                    path
+                },
+                _ => return,
+            };
+            match path {
+                QPath::Resolved(_, path) => path_prefix.with_path(path.segments),
+                QPath::TypeRelative(
+                    hir::Ty {
+                        kind: TyKind::Path(QPath::Resolved(_, path)),
+                        ..
+                    },
+                    _,
+                ) => path_prefix.with_prefix(path.segments),
+                _ => (),
             }
-        }
+        });
+    }
 
-        for arm in arms {
-            if arm.guard.is_some() {
-                // Guards mean that this case probably isn't exhaustively covered. Technically
-                // this is incorrect, as we should really check whether each variant is exhaustively
-                // covered by the set of guards that cover it, but that's really hard to do.
-                continue;
-            }
-            if let PatKind::Path(ref path) = arm.pat.kind {
-                if let QPath::Resolved(_, p) = path {
-                    missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id()));
-                }
-            } else if let PatKind::TupleStruct(QPath::Resolved(_, p), ref patterns, ..) = arm.pat.kind {
-                // Some simple checks for exhaustive patterns.
-                // There is a room for improvements to detect more cases,
-                // but it can be more expensive to do so.
-                let is_pattern_exhaustive =
-                    |pat: &&Pat<'_>| matches!(pat.kind, PatKind::Wild | PatKind::Binding(.., None));
-                if patterns.iter().all(is_pattern_exhaustive) {
-                    missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id()));
+    let format_suggestion = |variant: &VariantDef| {
+        format!(
+            "{}{}{}{}",
+            if let Some(ident) = wildcard_ident {
+                format!("{} @ ", ident.name)
+            } else {
+                String::new()
+            },
+            if let CommonPrefixSearcher::Path(path_prefix) = path_prefix {
+                let mut s = String::new();
+                for seg in path_prefix {
+                    s.push_str(&seg.ident.as_str());
+                    s.push_str("::");
                 }
+                s
+            } else {
+                let mut s = cx.tcx.def_path_str(adt_def.did);
+                s.push_str("::");
+                s
+            },
+            variant.ident.name,
+            match variant.ctor_kind {
+                CtorKind::Fn if variant.fields.len() == 1 => "(_)",
+                CtorKind::Fn => "(..)",
+                CtorKind::Const => "",
+                CtorKind::Fictive => "{ .. }",
             }
-        }
-
-        let mut suggestion: Vec<String> = missing_variants
-            .iter()
-            .map(|v| {
-                let suffix = match v.ctor_kind {
-                    CtorKind::Fn => "(..)",
-                    CtorKind::Const | CtorKind::Fictive => "",
-                };
-                let ident_str = if let Some(ident) = wildcard_ident {
-                    format!("{} @ ", ident.name)
-                } else {
-                    String::new()
-                };
-                // This path assumes that the enum type is imported into scope.
-                format!("{}{}{}", ident_str, cx.tcx.def_path_str(v.def_id), suffix)
-            })
-            .collect();
-
-        if suggestion.is_empty() {
-            return;
-        }
-
-        let mut message = "wildcard match will miss any future added variants";
+        )
+    };
 
-        if let ty::Adt(def, _) = ty.kind() {
-            if def.is_variant_list_non_exhaustive() {
-                message = "match on non-exhaustive enum doesn't explicitly match all known variants";
-                suggestion.push(String::from("_"));
-            }
-        }
+    match missing_variants.as_slice() {
+        [] => (),
+        [x] if !adt_def.is_variant_list_non_exhaustive() => span_lint_and_sugg(
+            cx,
+            MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
+            wildcard_span,
+            "wildcard matches only a single variant and will also match any future added variants",
+            "try this",
+            format_suggestion(x),
+            Applicability::MaybeIncorrect,
+        ),
+        variants => {
+            let mut suggestions: Vec<_> = variants.iter().cloned().map(format_suggestion).collect();
+            let message = if adt_def.is_variant_list_non_exhaustive() {
+                suggestions.push("_".into());
+                "wildcard matches known variants and will also match future added variants"
+            } else {
+                "wildcard match will also match any future added variants"
+            };
 
-        if suggestion.len() == 1 {
-            // No need to check for non-exhaustive enum as in that case len would be greater than 1
             span_lint_and_sugg(
                 cx,
-                MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
+                WILDCARD_ENUM_MATCH_ARM,
                 wildcard_span,
                 message,
                 "try this",
-                suggestion[0].clone(),
+                suggestions.join(" | "),
                 Applicability::MaybeIncorrect,
             )
-        };
-
-        span_lint_and_sugg(
-            cx,
-            WILDCARD_ENUM_MATCH_ARM,
-            wildcard_span,
-            message,
-            "try this",
-            suggestion.join(" | "),
-            Applicability::MaybeIncorrect,
-        )
-    }
+        },
+    };
 }
 
 // If the block contains only a `panic!` macro (as expression or statement)
@@ -1284,6 +1354,7 @@ fn find_bool_lit(ex: &ExprKind<'_>, desugared: bool) -> Option<bool> {
     }
 }
 
+#[allow(clippy::too_many_lines)]
 fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], expr: &Expr<'_>) {
     if in_macro(expr.span) || arms.len() != 1 || is_refutable(cx, arms[0].pat) {
         return;
@@ -1358,7 +1429,18 @@ fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[A
                         indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
                         cbrace_start = format!("{{\n{}", indent);
                     }
-                };
+                }
+                // If the parent is already an arm, and the body is another match statement,
+                // we need curly braces around suggestion
+                let parent_node_id = cx.tcx.hir().get_parent_node(expr.hir_id);
+                if let Node::Arm(arm) = &cx.tcx.hir().get(parent_node_id) {
+                    if let ExprKind::Match(..) = arm.body.kind {
+                        cbrace_end = format!("\n{}}}", indent);
+                        // Fix body indent due to the match
+                        indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
+                        cbrace_start = format!("{{\n{}", indent);
+                    }
+                }
                 (
                     expr.span,
                     format!(
@@ -1587,7 +1669,7 @@ where
 
     values.sort();
 
-    for (a, b) in values.iter().zip(values.iter().skip(1)) {
+    for (a, b) in iter::zip(&values, &values[1..]) {
         match (a, b) {
             (&Kind::Start(_, ra), &Kind::End(_, rb)) => {
                 if ra.node != rb.node {
@@ -1614,7 +1696,9 @@ where
 
 mod redundant_pattern_match {
     use super::REDUNDANT_PATTERN_MATCHING;
-    use crate::utils::{match_qpath, match_trait_method, paths, snippet, span_lint_and_then};
+    use clippy_utils::diagnostics::span_lint_and_then;
+    use clippy_utils::source::snippet;
+    use clippy_utils::{is_trait_method, match_qpath, paths};
     use if_chain::if_chain;
     use rustc_ast::ast::LitKind;
     use rustc_errors::Applicability;
@@ -1679,7 +1763,7 @@ mod redundant_pattern_match {
             if keyword == "while";
             if let ExprKind::MethodCall(method_path, _, _, _) = op.kind;
             if method_path.ident.name == sym::next;
-            if match_trait_method(cx, op, &paths::ITERATOR);
+            if is_trait_method(cx, op, sym::Iterator);
             then {
                 return;
             }
diff --git a/src/tools/clippy/clippy_lints/src/mem_discriminant.rs b/src/tools/clippy/clippy_lints/src/mem_discriminant.rs
index c71c2ee7d70..7895ba9f1e0 100644
--- a/src/tools/clippy/clippy_lints/src/mem_discriminant.rs
+++ b/src/tools/clippy/clippy_lints/src/mem_discriminant.rs
@@ -1,10 +1,12 @@
-use crate::utils::{match_def_path, paths, snippet, span_lint_and_then, walk_ptrs_ty_depth};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::walk_ptrs_ty_depth;
+use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-
 use std::iter;
 
 declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/mem_forget.rs b/src/tools/clippy/clippy_lints/src/mem_forget.rs
index d34f9761e26..c13802e3953 100644
--- a/src/tools/clippy/clippy_lints/src/mem_forget.rs
+++ b/src/tools/clippy/clippy_lints/src/mem_forget.rs
@@ -1,4 +1,5 @@
-use crate::utils::{match_def_path, paths, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{match_def_path, paths};
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs
index 19087b02077..426c108d89f 100644
--- a/src/tools/clippy/clippy_lints/src/mem_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs
@@ -1,9 +1,10 @@
-use crate::utils::{
-    in_macro, match_def_path, match_qpath, meets_msrv, paths, snippet, snippet_with_applicability, span_lint_and_help,
-    span_lint_and_sugg, span_lint_and_then,
-};
+use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::is_diagnostic_assoc_item;
+use clippy_utils::source::{snippet, snippet_with_applicability};
+use clippy_utils::{in_macro, match_def_path, match_qpath, meets_msrv, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
+use rustc_hir::def_id::DefId;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, QPath};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
@@ -194,13 +195,44 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'
     }
 }
 
+/// Returns true if the `def_id` associated with the `path` is recognized as a "default-equivalent"
+/// constructor from the std library
+fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<'_>) -> bool {
+    let std_types_symbols = &[
+        sym::string_type,
+        sym::vec_type,
+        sym::vecdeque_type,
+        sym::LinkedList,
+        sym::hashmap_type,
+        sym::BTreeMap,
+        sym::hashset_type,
+        sym::BTreeSet,
+        sym::BinaryHeap,
+    ];
+
+    if std_types_symbols
+        .iter()
+        .any(|symbol| is_diagnostic_assoc_item(cx, def_id, *symbol))
+    {
+        if let QPath::TypeRelative(_, ref method) = path {
+            if method.ident.name == sym::new {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
 fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) {
     if let ExprKind::Call(ref repl_func, _) = src.kind {
         if_chain! {
             if !in_external_macro(cx.tcx.sess, expr_span);
             if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
             if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
-            if match_def_path(cx, repl_def_id, &paths::DEFAULT_TRAIT_METHOD);
+            if is_diagnostic_assoc_item(cx, repl_def_id, sym::Default)
+                || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath);
+
             then {
                 span_lint_and_then(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
index 5decb81d9f2..0ba8a98a018 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -1,8 +1,8 @@
 use super::{contains_return, BIND_INSTEAD_OF_MAP};
-use crate::utils::{
-    in_macro, match_qpath, match_type, method_calls, multispan_sugg_with_applicability, paths, remove_blocks, snippet,
-    snippet_with_macro_callsite, span_lint_and_sugg, span_lint_and_then, visitors::find_all_ret_expressions,
-};
+use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::source::{snippet, snippet_with_macro_callsite};
+use clippy_utils::ty::match_type;
+use clippy_utils::{in_macro, match_qpath, method_calls, paths, remove_blocks, visitors::find_all_ret_expressions};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
diff --git a/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs b/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs
index 71a7e195e41..4f88f80a304 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs
@@ -1,4 +1,6 @@
-use crate::utils::{is_type_diagnostic_item, snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::is_type_diagnostic_item;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs b/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs
new file mode 100644
index 00000000000..c668fe52781
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs
@@ -0,0 +1,54 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::{method_chain_args, single_segment_path};
+use if_chain::if_chain;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_lint::LateContext;
+use rustc_lint::Lint;
+use rustc_middle::ty;
+use rustc_span::sym;
+
+/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints.
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    info: &crate::methods::BinaryExprInfo<'_>,
+    chain_methods: &[&str],
+    lint: &'static Lint,
+    suggest: &str,
+) -> bool {
+    if_chain! {
+        if let Some(args) = method_chain_args(info.chain, chain_methods);
+        if let hir::ExprKind::Call(ref fun, ref arg_char) = info.other.kind;
+        if arg_char.len() == 1;
+        if let hir::ExprKind::Path(ref qpath) = fun.kind;
+        if let Some(segment) = single_segment_path(qpath);
+        if segment.ident.name == sym::Some;
+        then {
+            let mut applicability = Applicability::MachineApplicable;
+            let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0][0]).peel_refs();
+
+            if *self_ty.kind() != ty::Str {
+                return false;
+            }
+
+            span_lint_and_sugg(
+                cx,
+                lint,
+                info.expr.span,
+                &format!("you should use the `{}` method", suggest),
+                "like this",
+                format!("{}{}.{}({})",
+                        if info.eq { "" } else { "!" },
+                        snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
+                        suggest,
+                        snippet_with_applicability(cx, arg_char[0].span, "..", &mut applicability)),
+                applicability,
+            );
+
+            return true;
+        }
+    }
+
+    false
+}
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
new file mode 100644
index 00000000000..4275857757f
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
@@ -0,0 +1,44 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::method_chain_args;
+use clippy_utils::source::snippet_with_applicability;
+use if_chain::if_chain;
+use rustc_ast::ast;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+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>,
+    info: &crate::methods::BinaryExprInfo<'_>,
+    chain_methods: &[&str],
+    lint: &'static Lint,
+    suggest: &str,
+) -> bool {
+    if_chain! {
+        if let Some(args) = method_chain_args(info.chain, chain_methods);
+        if let hir::ExprKind::Lit(ref lit) = info.other.kind;
+        if let ast::LitKind::Char(c) = lit.node;
+        then {
+            let mut applicability = Applicability::MachineApplicable;
+            span_lint_and_sugg(
+                cx,
+                lint,
+                info.expr.span,
+                &format!("you should use the `{}` method", suggest),
+                "like this",
+                format!("{}{}.{}('{}')",
+                        if info.eq { "" } else { "!" },
+                        snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
+                        suggest,
+                        c),
+                applicability,
+            );
+
+            true
+        } else {
+            false
+        }
+    }
+}
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
new file mode 100644
index 00000000000..07bbc5ca1bf
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp.rs
@@ -0,0 +1,13 @@
+use crate::methods::chars_cmp;
+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 {
+    if chars_cmp::check(cx, info, &["chars", "last"], CHARS_LAST_CMP, "ends_with") {
+        true
+    } else {
+        chars_cmp::check(cx, info, &["chars", "next_back"], CHARS_LAST_CMP, "ends_with")
+    }
+}
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
new file mode 100644
index 00000000000..c29ee0ec8c8
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs
@@ -0,0 +1,13 @@
+use crate::methods::chars_cmp_with_unwrap;
+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 {
+    if chars_cmp_with_unwrap::check(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") {
+        true
+    } else {
+        chars_cmp_with_unwrap::check(cx, info, &["chars", "next_back", "unwrap"], CHARS_LAST_CMP, "ends_with")
+    }
+}
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
new file mode 100644
index 00000000000..a6701d8830e
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp.rs
@@ -0,0 +1,8 @@
+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 {
+    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
new file mode 100644
index 00000000000..28ede28e935
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs
@@ -0,0 +1,8 @@
+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 {
+    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/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
index 4a130ed47db..edb6649b87b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
@@ -1,15 +1,23 @@
-use crate::utils::{is_copy, span_lint_and_then, sugg};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sugg;
+use clippy_utils::ty::is_copy;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty;
+use rustc_span::symbol::{sym, Symbol};
 use std::iter;
 
 use super::CLONE_DOUBLE_REF;
 use super::CLONE_ON_COPY;
 
 /// Checks for the `CLONE_ON_COPY` lint.
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, arg_ty: Ty<'_>) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) {
+    if !(args.len() == 1 && method_name == sym::clone) {
+        return;
+    }
+    let arg = &args[0];
+    let arg_ty = cx.typeck_results().expr_ty_adjusted(&args[0]);
     let ty = cx.typeck_results().expr_ty(expr);
     if let ty::Ref(_, inner, _) = arg_ty.kind() {
         if let ty::Ref(_, innermost, _) = inner.kind() {
diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
index 3d5a68d69d7..6417bc81304 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
@@ -1,13 +1,20 @@
-use crate::utils::{is_type_diagnostic_item, match_type, paths, snippet_with_macro_callsite, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::paths;
+use clippy_utils::source::snippet_with_macro_callsite;
+use clippy_utils::ty::{is_type_diagnostic_item, match_type};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::symbol::sym;
+use rustc_span::symbol::{sym, Symbol};
 
 use super::CLONE_ON_REF_PTR;
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) {
+    if !(args.len() == 1 && method_name == sym::clone) {
+        return;
+    }
+    let arg = &args[0];
     let obj_ty = cx.typeck_results().expr_ty(arg).peel_refs();
 
     if let ty::Adt(_, subst) = obj_ty.kind() {
diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
index 6866e9c652a..e7bffa66b3f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
@@ -1,4 +1,7 @@
-use crate::utils::{is_expn_of, is_type_diagnostic_item, snippet, snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_expn_of;
+use clippy_utils::source::{snippet, snippet_with_applicability};
+use clippy_utils::ty::is_type_diagnostic_item;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
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 90b781bd9d1..64531b29ade 100644
--- a/src/tools/clippy/clippy_lints/src/methods/expect_used.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/expect_used.rs
@@ -1,4 +1,5 @@
-use crate::utils::{is_type_diagnostic_item, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_span::sym;
diff --git a/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs b/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
index b03835f97e6..39d2f15dbc8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
@@ -1,4 +1,6 @@
-use crate::utils::{get_parent_expr, match_type, paths, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::ty::match_type;
+use clippy_utils::{get_parent_expr, paths};
 use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_flat_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_flat_map.rs
index 8da867fce51..1588eec8882 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_flat_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_flat_map.rs
@@ -1,18 +1,15 @@
-use crate::utils::{match_trait_method, paths, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::is_trait_method;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
+use rustc_span::sym;
 
 use super::FILTER_MAP;
 
 /// lint use of `filter().flat_map()` for `Iterators`
-pub(super) fn check<'tcx>(
-    cx: &LateContext<'tcx>,
-    expr: &'tcx hir::Expr<'_>,
-    _filter_args: &'tcx [hir::Expr<'_>],
-    _map_args: &'tcx [hir::Expr<'_>],
-) {
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
     // lint if caller of `.filter().flat_map()` is an Iterator
-    if match_trait_method(cx, expr, &paths::ITERATOR) {
+    if is_trait_method(cx, expr, sym::Iterator) {
         let msg = "called `filter(..).flat_map(..)` on an `Iterator`";
         let hint = "this is more succinctly expressed by calling `.flat_map(..)` \
                     and filtering by returning `iter::empty()`";
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 f559160004c..2cb476acb2b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
@@ -1,4 +1,6 @@
-use crate::utils::{match_trait_method, path_to_local_id, paths, snippet, span_lint_and_sugg, SpanlessEq};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::{is_trait_method, path_to_local_id, SpanlessEq};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -15,7 +17,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, is_
     if_chain! {
         if let ExprKind::MethodCall(_, _, [map_recv, map_arg], map_span) = expr.kind;
         if let ExprKind::MethodCall(_, _, [_, filter_arg], filter_span) = map_recv.kind;
-        if match_trait_method(cx, map_recv, &paths::ITERATOR);
+        if is_trait_method(cx, map_recv, sym::Iterator);
 
         // filter(|x| ...is_some())...
         if let ExprKind::Closure(_, _, filter_body_id, ..) = filter_arg.kind;
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_flat_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_flat_map.rs
index a6db138623a..741b1e7e361 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map_flat_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_flat_map.rs
@@ -1,18 +1,15 @@
-use crate::utils::{match_trait_method, paths, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::is_trait_method;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
+use rustc_span::sym;
 
 use super::FILTER_MAP;
 
 /// lint use of `filter_map().flat_map()` for `Iterators`
-pub(super) fn check<'tcx>(
-    cx: &LateContext<'tcx>,
-    expr: &'tcx hir::Expr<'_>,
-    _filter_args: &'tcx [hir::Expr<'_>],
-    _map_args: &'tcx [hir::Expr<'_>],
-) {
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
     // lint if caller of `.filter_map().flat_map()` is an Iterator
-    if match_trait_method(cx, expr, &paths::ITERATOR) {
+    if is_trait_method(cx, expr, sym::Iterator) {
         let msg = "called `filter_map(..).flat_map(..)` on an `Iterator`";
         let hint = "this is more succinctly expressed by calling `.flat_map(..)` \
                     and filtering by returning `iter::empty()`";
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs
index 9e646360a40..80598d88508 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs
@@ -1,9 +1,10 @@
-use crate::utils::{match_qpath, match_trait_method, path_to_local_id, paths, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::{is_trait_method, match_qpath, path_to_local_id, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_span::source_map::Span;
+use rustc_span::{source_map::Span, sym};
 
 use super::FILTER_MAP_IDENTITY;
 
@@ -13,7 +14,7 @@ pub(super) fn check(
     filter_map_args: &[hir::Expr<'_>],
     filter_map_span: Span,
 ) {
-    if match_trait_method(cx, expr, &paths::ITERATOR) {
+    if is_trait_method(cx, expr, sym::Iterator) {
         let arg_node = &filter_map_args[1].kind;
 
         let apply_lint = |message: &str| {
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_map.rs
index d015b4c7b38..713bbf25837 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_map.rs
@@ -1,18 +1,15 @@
-use crate::utils::{match_trait_method, paths, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::is_trait_method;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
+use rustc_span::sym;
 
 use super::FILTER_MAP;
 
 /// lint use of `filter_map().map()` for `Iterators`
-pub(super) fn check<'tcx>(
-    cx: &LateContext<'tcx>,
-    expr: &'tcx hir::Expr<'_>,
-    _filter_args: &'tcx [hir::Expr<'_>],
-    _map_args: &'tcx [hir::Expr<'_>],
-) {
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
     // lint if caller of `.filter_map().map()` is an Iterator
-    if match_trait_method(cx, expr, &paths::ITERATOR) {
+    if is_trait_method(cx, expr, sym::Iterator) {
         let msg = "called `filter_map(..).map(..)` on an `Iterator`";
         let hint = "this is more succinctly expressed by only calling `.filter_map(..)` instead";
         span_lint_and_help(cx, FILTER_MAP, expr.span, msg, None, hint);
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs
index a789df922ff..ba57abd16c9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs
@@ -1,8 +1,11 @@
-use crate::utils::{match_trait_method, meets_msrv, paths, snippet, span_lint, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::source::snippet;
+use clippy_utils::{is_trait_method, meets_msrv};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_semver::RustcVersion;
+use rustc_span::sym;
 
 use super::FILTER_MAP_NEXT;
 
@@ -14,7 +17,7 @@ pub(super) fn check<'tcx>(
     filter_args: &'tcx [hir::Expr<'_>],
     msrv: Option<&RustcVersion>,
 ) {
-    if match_trait_method(cx, expr, &paths::ITERATOR) {
+    if is_trait_method(cx, expr, sym::Iterator) {
         if !meets_msrv(msrv, &FILTER_MAP_NEXT_MSRV) {
             return;
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
index 81619e73017..6cd24334414 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
@@ -1,14 +1,17 @@
-use crate::utils::{match_trait_method, paths, snippet, span_lint, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::is_trait_method;
+use clippy_utils::source::snippet;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
+use rustc_span::sym;
 
 use super::FILTER_NEXT;
 
 /// lint use of `filter().next()` for `Iterators`
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, filter_args: &'tcx [hir::Expr<'_>]) {
     // lint if caller of `.filter().next()` is an Iterator
-    if match_trait_method(cx, expr, &paths::ITERATOR) {
+    if is_trait_method(cx, expr, sym::Iterator) {
         let msg = "called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling \
                    `.find(..)` instead";
         let filter_snippet = snippet(cx, filter_args[1].span, "..");
diff --git a/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs
index ce3194f8a23..034ea6c6562 100644
--- a/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs
@@ -1,9 +1,10 @@
-use crate::utils::{match_qpath, match_trait_method, paths, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::{is_trait_method, match_qpath, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_span::source_map::Span;
+use rustc_span::{source_map::Span, sym};
 
 use super::FLAT_MAP_IDENTITY;
 
@@ -14,7 +15,7 @@ pub(super) fn check<'tcx>(
     flat_map_args: &'tcx [hir::Expr<'_>],
     flat_map_span: Span,
 ) {
-    if match_trait_method(cx, expr, &paths::ITERATOR) {
+    if is_trait_method(cx, expr, sym::Iterator) {
         let arg_node = &flat_map_args[1].kind;
 
         let apply_lint = |message: &str| {
diff --git a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
index e50d0a33400..15cf5674313 100644
--- a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
@@ -1,19 +1,24 @@
-use crate::utils::{get_trait_def_id, implements_trait, paths, span_lint_and_sugg, sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::ty::implements_trait;
+use clippy_utils::{get_trait_def_id, match_qpath, paths, sugg};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::ExprKind;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty::Ty;
+use rustc_span::sym;
 
 use super::FROM_ITER_INSTEAD_OF_COLLECT;
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
-    let ty = cx.typeck_results().expr_ty(expr);
-    let arg_ty = cx.typeck_results().expr_ty(&args[0]);
-
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>], func_kind: &ExprKind<'_>) {
     if_chain! {
+        if let hir::ExprKind::Path(path) = func_kind;
+        if match_qpath(path, &["from_iter"]);
+        let ty = cx.typeck_results().expr_ty(expr);
+        let arg_ty = cx.typeck_results().expr_ty(&args[0]);
         if let Some(from_iter_id) = get_trait_def_id(cx, &paths::FROM_ITERATOR);
-        if let Some(iter_id) = get_trait_def_id(cx, &paths::ITERATOR);
+        if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
 
         if implements_trait(cx, ty, from_iter_id, &[]) && implements_trait(cx, arg_ty, iter_id, &[]);
         then {
diff --git a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
index e157db2712a..b3a9743c614 100644
--- a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
@@ -1,7 +1,8 @@
-use crate::methods::derefs_to_slice;
-use crate::utils::{
-    get_parent_expr, is_type_diagnostic_item, match_type, paths, snippet_with_applicability, span_lint_and_sugg,
-};
+use super::utils::derefs_to_slice;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::{is_type_diagnostic_item, match_type};
+use clippy_utils::{get_parent_expr, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
index a769493d11d..04461ad5c3a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
@@ -1,4 +1,4 @@
-use crate::utils::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_sugg;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
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 3045b09c238..950ec62c9fe 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
@@ -1,20 +1,24 @@
-use super::INEFFICIENT_TO_STRING;
-use crate::utils::{
-    is_type_diagnostic_item, match_def_path, paths, snippet_with_applicability, span_lint_and_then, walk_ptrs_ty_depth,
-};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::{is_type_diagnostic_item, walk_ptrs_ty_depth};
+use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::sym;
+use rustc_span::symbol::{sym, Symbol};
+
+use super::INEFFICIENT_TO_STRING;
 
 /// Checks for the `INEFFICIENT_TO_STRING` lint
-pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, arg_ty: Ty<'tcx>) {
+pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) {
     if_chain! {
+        if args.len() == 1 && method_name == sym!(to_string);
         if let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if match_def_path(cx, to_string_meth_did, &paths::TO_STRING_METHOD);
         if let Some(substs) = cx.typeck_results().node_substs_opt(expr.hir_id);
+        let arg_ty = cx.typeck_results().expr_ty_adjusted(&args[0]);
         let self_ty = substs.type_at(0);
         let (deref_self_ty, deref_count) = walk_ptrs_ty_depth(self_ty);
         if deref_count >= 1;
@@ -31,7 +35,7 @@ pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &hir::Expr
                         self_ty, deref_self_ty
                     ));
                     let mut applicability = Applicability::MachineApplicable;
-                    let arg_snippet = snippet_with_applicability(cx, arg.span, "..", &mut applicability);
+                    let arg_snippet = snippet_with_applicability(cx, args[0].span, "..", &mut applicability);
                     diag.span_suggestion(
                         expr.span,
                         "try dereferencing the receiver",
diff --git a/src/tools/clippy/clippy_lints/src/methods/inspect_for_each.rs b/src/tools/clippy/clippy_lints/src/methods/inspect_for_each.rs
index 959457a5bfc..7fd3ef1a622 100644
--- a/src/tools/clippy/clippy_lints/src/methods/inspect_for_each.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/inspect_for_each.rs
@@ -1,14 +1,14 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::is_trait_method;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_span::source_map::Span;
-
-use crate::utils::{match_trait_method, paths, span_lint_and_help};
+use rustc_span::{source_map::Span, sym};
 
 use super::INSPECT_FOR_EACH;
 
 /// lint use of `inspect().for_each()` for `Iterators`
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, inspect_span: Span) {
-    if match_trait_method(cx, expr, &paths::ITERATOR) {
+    if is_trait_method(cx, expr, sym::Iterator) {
         let msg = "called `inspect(..).for_each(..)` on an `Iterator`";
         let hint = "move the code from `inspect(..)` to `for_each(..)` and remove the `inspect(..)`";
         span_lint_and_help(
diff --git a/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs b/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs
index 1e8315dbee2..da13b4ba37a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs
@@ -1,30 +1,43 @@
-use crate::utils::{has_iter_method, match_trait_method, paths, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_trait_method;
+use clippy_utils::ty::has_iter_method;
+use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::source_map::Span;
-use rustc_span::symbol::Symbol;
+use rustc_span::symbol::{sym, Symbol};
 
 use super::INTO_ITER_ON_REF;
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, self_ref_ty: Ty<'_>, method_span: Span) {
-    if !match_trait_method(cx, expr, &paths::INTO_ITERATOR) {
-        return;
-    }
-    if let Some((kind, method_name)) = ty_has_iter_method(cx, self_ref_ty) {
-        span_lint_and_sugg(
-            cx,
-            INTO_ITER_ON_REF,
-            method_span,
-            &format!(
-                "this `.into_iter()` call is equivalent to `.{}()` and will not consume the `{}`",
-                method_name, kind,
-            ),
-            "call directly",
-            method_name.to_string(),
-            Applicability::MachineApplicable,
-        );
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    method_span: Span,
+    method_name: Symbol,
+    args: &[hir::Expr<'_>],
+) {
+    let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0]);
+    if_chain! {
+        if let ty::Ref(..) = self_ty.kind();
+        if method_name == sym::into_iter;
+        if is_trait_method(cx, expr, sym::IntoIterator);
+        if let Some((kind, method_name)) = ty_has_iter_method(cx, self_ty);
+        then {
+            span_lint_and_sugg(
+                cx,
+                INTO_ITER_ON_REF,
+                method_span,
+                &format!(
+                    "this `.into_iter()` call is equivalent to `.{}()` and will not consume the `{}`",
+                    method_name, kind,
+                ),
+                "call directly",
+                method_name.to_string(),
+                Applicability::MachineApplicable,
+            );
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs b/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs
index c3e48ffa5fa..848f47e39f6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs
@@ -1,5 +1,6 @@
-use crate::methods::derefs_to_slice;
-use crate::utils::{is_type_diagnostic_item, span_lint_and_sugg};
+use crate::methods::utils::derefs_to_slice;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_count.rs b/src/tools/clippy/clippy_lints/src/methods/iter_count.rs
index 869440e0165..e394a8fe819 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_count.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_count.rs
@@ -1,6 +1,8 @@
-use crate::methods::derefs_to_slice;
-use crate::utils::{is_type_diagnostic_item, match_type, paths, snippet_with_applicability, span_lint_and_sugg};
-
+use super::utils::derefs_to_slice;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::paths;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::{is_type_diagnostic_item, match_type};
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs
index 3c03a949cfe..e9b37b6f2bd 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs
@@ -1,5 +1,8 @@
-use crate::methods::derefs_to_slice;
-use crate::utils::{get_parent_expr, higher, is_type_diagnostic_item, snippet_with_applicability, span_lint_and_sugg};
+use super::utils::derefs_to_slice;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{get_parent_expr, higher};
 use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_errors::Applicability;
@@ -44,12 +47,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, ite
                 );
             }
         }
-    } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(caller_expr), sym::vec_type)
-        || matches!(
-            &cx.typeck_results().expr_ty(caller_expr).peel_refs().kind(),
-            ty::Array(_, _)
-        )
-    {
+    } else if is_vec_or_array(cx, caller_expr) {
         // caller is a Vec or an Array
         let mut applicability = Applicability::MachineApplicable;
         span_lint_and_sugg(
@@ -66,3 +64,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, ite
         );
     }
 }
+
+fn is_vec_or_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) -> bool {
+    is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::vec_type)
+        || matches!(&cx.typeck_results().expr_ty(expr).peel_refs().kind(), ty::Array(_, _))
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
index cc3e56ea872..c46af427b3c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
@@ -1,6 +1,7 @@
-use crate::methods::derefs_to_slice;
+use super::utils::derefs_to_slice;
 use crate::methods::iter_nth_zero;
-use crate::utils::{is_type_diagnostic_item, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
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 247192d81f3..a12f672739c 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
@@ -1,15 +1,18 @@
 use crate::consts::{constant, Constant};
-use crate::utils::{match_trait_method, paths, snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_trait_method;
+use clippy_utils::source::snippet_with_applicability;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
+use rustc_span::sym;
 
 use super::ITER_NTH_ZERO;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, nth_args: &'tcx [hir::Expr<'_>]) {
     if_chain! {
-        if match_trait_method(cx, expr, &paths::ITERATOR);
+        if is_trait_method(cx, expr, sym::Iterator);
         if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), &nth_args[1]);
         then {
             let mut applicability = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs b/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs
index 5f5969134e4..b1d398876d3 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs
@@ -1,22 +1,24 @@
-use crate::utils::{match_trait_method, paths, snippet, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_trait_method;
+use clippy_utils::source::snippet;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
+use rustc_span::sym;
 
 use super::ITER_SKIP_NEXT;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, skip_args: &[hir::Expr<'_>]) {
     // lint if caller of skip is an Iterator
-    if match_trait_method(cx, expr, &paths::ITERATOR) {
+    if is_trait_method(cx, expr, sym::Iterator) {
         if let [caller, n] = skip_args {
-            let hint = format!(".nth({})", snippet(cx, n.span, ".."));
             span_lint_and_sugg(
                 cx,
                 ITER_SKIP_NEXT,
                 expr.span.trim_start(caller.span).unwrap(),
                 "called `skip(..).next()` on an iterator",
                 "use `nth` instead",
-                hint,
+                format!(".nth({})", snippet(cx, n.span, "..")),
                 Applicability::MachineApplicable,
             );
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
index 3e05d7f76b7..3baa580314f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
@@ -1,12 +1,14 @@
 use crate::consts::{constant, Constant};
-use crate::utils::{match_trait_method, paths, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::is_trait_method;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
+use rustc_span::sym;
 
 use super::ITERATOR_STEP_BY_ZERO;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, args: &'tcx [hir::Expr<'_>]) {
-    if match_trait_method(cx, expr, &paths::ITERATOR) {
+    if is_trait_method(cx, expr, sym::Iterator) {
         if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), &args[1]) {
             span_lint(
                 cx,
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 0b414e0eb95..f16699322d1 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
@@ -1,4 +1,6 @@
-use crate::utils::{match_qpath, snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::match_qpath;
+use clippy_utils::source::snippet_with_applicability;
 use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_errors::Applicability;
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 5b20e268d9f..e4402b2da21 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,4 +1,7 @@
-use crate::utils::{is_type_diagnostic_item, match_trait_method, paths, snippet, span_lint_and_sugg};
+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;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -17,7 +20,7 @@ pub(super) fn check(
     if_chain! {
         // called on Iterator
         if let [map_expr] = collect_args;
-        if match_trait_method(cx, map_expr, &paths::ITERATOR);
+        if is_trait_method(cx, map_expr, 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_type);
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
index 14a14e4f9ec..4bc52b036a8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
@@ -1,4 +1,7 @@
-use crate::utils::{is_type_diagnostic_item, match_trait_method, paths, snippet, span_lint_and_sugg};
+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 rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -10,7 +13,7 @@ use super::MAP_FLATTEN;
 /// lint use of `map().flatten()` for `Iterators` and 'Options'
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map_args: &'tcx [hir::Expr<'_>]) {
     // lint if caller of `.map().flatten()` is an Iterator
-    if match_trait_method(cx, expr, &paths::ITERATOR) {
+    if is_trait_method(cx, expr, sym::Iterator) {
         let map_closure_ty = cx.typeck_results().expr_ty(&map_args[1]);
         let is_map_to_option = match map_closure_ty.kind() {
             ty::Closure(_, _) | ty::FnDef(_, _) | ty::FnPtr(_) => {
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs
index 63b2cf87f32..deb4b4492b5 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs
@@ -1,5 +1,8 @@
-use crate::utils::usage::mutated_variables;
-use crate::utils::{is_type_diagnostic_item, meets_msrv, snippet, span_lint, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::meets_msrv;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::usage::mutated_variables;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 7fd14c4f9b1..fccdee07877 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -1,5 +1,11 @@
 mod bind_instead_of_map;
 mod bytes_nth;
+mod chars_cmp;
+mod chars_cmp_with_unwrap;
+mod chars_last_cmp;
+mod chars_last_cmp_with_unwrap;
+mod chars_next_cmp;
+mod chars_next_cmp_with_unwrap;
 mod clone_on_copy;
 mod clone_on_ref_ptr;
 mod expect_fun_call;
@@ -36,6 +42,7 @@ mod option_map_or_none;
 mod option_map_unwrap_or;
 mod or_fun_call;
 mod search_is_some;
+mod single_char_add_str;
 mod single_char_insert_string;
 mod single_char_pattern;
 mod single_char_push_string;
@@ -48,16 +55,19 @@ mod unnecessary_fold;
 mod unnecessary_lazy_eval;
 mod unwrap_used;
 mod useless_asref;
+mod utils;
 mod wrong_self_convention;
 mod zst_offset;
 
 use bind_instead_of_map::BindInsteadOfMap;
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::ty::{contains_adt_constructor, contains_ty, implements_trait, is_copy, is_type_diagnostic_item};
+use clippy_utils::{contains_return, get_trait_def_id, in_macro, iter_input_pats, method_calls, paths, return_ty};
 use if_chain::if_chain;
-use rustc_ast::ast;
-use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::{TraitItem, TraitItemKind};
-use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
+use rustc_hir::def::Res;
+use rustc_hir::{PrimTy, QPath, TraitItem, TraitItemKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, TraitRef, Ty, TyS};
 use rustc_semver::RustcVersion;
@@ -65,12 +75,6 @@ use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::{sym, SymbolStr};
 use rustc_typeck::hir_ty_to_ty;
 
-use crate::utils::{
-    contains_return, contains_ty, get_trait_def_id, implements_trait, in_macro, is_copy, is_type_diagnostic_item,
-    iter_input_pats, match_def_path, match_qpath, method_calls, method_chain_args, paths, return_ty,
-    single_segment_path, snippet_with_applicability, span_lint, span_lint_and_help, span_lint_and_sugg, SpanlessEq,
-};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for `.unwrap()` calls on `Option`s and on `Result`s.
     ///
@@ -191,13 +195,18 @@ declare_clippy_lint! {
     /// **What it does:** Checks for methods with certain name prefixes and which
     /// doesn't match how self is taken. The actual rules are:
     ///
-    /// |Prefix |`self` taken          |
-    /// |-------|----------------------|
-    /// |`as_`  |`&self` or `&mut self`|
-    /// |`from_`| none                 |
-    /// |`into_`|`self`                |
-    /// |`is_`  |`&self` or none       |
-    /// |`to_`  |`&self`               |
+    /// |Prefix |Postfix     |`self` taken           | `self` type  |
+    /// |-------|------------|-----------------------|--------------|
+    /// |`as_`  | none       |`&self` or `&mut self` | any          |
+    /// |`from_`| none       | none                  | any          |
+    /// |`into_`| none       |`self`                 | any          |
+    /// |`is_`  | none       |`&self` or none        | any          |
+    /// |`to_`  | `_mut`     |`&mut self`            | any          |
+    /// |`to_`  | not `_mut` |`self`                 | `Copy`       |
+    /// |`to_`  | not `_mut` |`&self`                | not `Copy`   |
+    ///
+    /// 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
@@ -582,26 +591,31 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// **What it does:** Checks for an iterator or string search (such as `find()`,
-    /// `position()`, or `rposition()`) followed by a call to `is_some()`.
+    /// `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(_)`.
+    /// **Why is this bad?** Readability, this can be written more concisely as:
+    /// * `_.any(_)`, or `_.contains(_)` for `is_some()`,
+    /// * `!_.any(_)`, or `!_.contains(_)` for `is_none()`.
     ///
     /// **Known problems:** None.
     ///
     /// **Example:**
     /// ```rust
-    /// # let vec = vec![1];
+    /// let vec = vec![1];
     /// vec.iter().find(|x| **x == 0).is_some();
+    ///
+    /// let _ = "hello world".find("world").is_none();
     /// ```
     /// Could be written as
     /// ```rust
-    /// # let vec = vec![1];
+    /// let vec = vec![1];
     /// vec.iter().any(|x| *x == 0);
+    ///
+    /// let _ = !"hello world".contains("world");
     /// ```
     pub SEARCH_IS_SOME,
     complexity,
-    "using an iterator or string search followed by `is_some()`, which is more succinctly expressed as a call to `any()` or `contains()`"
+    "using an iterator or string search followed by `is_some()` or `is_none()`, which is more succinctly expressed as a call to `any()` or `contains()` (with negation in case of `is_none()`)"
 }
 
 declare_clippy_lint! {
@@ -1707,19 +1721,49 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
             ["next", "skip_while"] => skip_while_next::check(cx, expr, arg_lists[1]),
             ["next", "iter"] => iter_next_slice::check(cx, expr, arg_lists[1]),
             ["map", "filter"] => filter_map::check(cx, expr, false),
-            ["map", "filter_map"] => filter_map_map::check(cx, expr, arg_lists[1], arg_lists[0]),
+            ["map", "filter_map"] => filter_map_map::check(cx, expr),
             ["next", "filter_map"] => filter_map_next::check(cx, expr, arg_lists[1], self.msrv.as_ref()),
             ["map", "find"] => filter_map::check(cx, expr, true),
-            ["flat_map", "filter"] => filter_flat_map::check(cx, expr, arg_lists[1], arg_lists[0]),
-            ["flat_map", "filter_map"] => filter_map_flat_map::check(cx, expr, arg_lists[1], arg_lists[0]),
+            ["flat_map", "filter"] => filter_flat_map::check(cx, expr),
+            ["flat_map", "filter_map"] => filter_map_flat_map::check(cx, expr),
             ["flat_map", ..] => flat_map_identity::check(cx, expr, arg_lists[0], method_spans[0]),
             ["flatten", "map"] => map_flatten::check(cx, expr, arg_lists[1]),
-            ["is_some", "find"] => search_is_some::check(cx, expr, "find", arg_lists[1], arg_lists[0], method_spans[1]),
-            ["is_some", "position"] => {
-                search_is_some::check(cx, expr, "position", arg_lists[1], arg_lists[0], method_spans[1])
+            [option_check_method, "find"] if "is_some" == *option_check_method || "is_none" == *option_check_method => {
+                search_is_some::check(
+                    cx,
+                    expr,
+                    "find",
+                    option_check_method,
+                    arg_lists[1],
+                    arg_lists[0],
+                    method_spans[1],
+                )
             },
-            ["is_some", "rposition"] => {
-                search_is_some::check(cx, expr, "rposition", arg_lists[1], arg_lists[0], method_spans[1])
+            [option_check_method, "position"]
+                if "is_some" == *option_check_method || "is_none" == *option_check_method =>
+            {
+                search_is_some::check(
+                    cx,
+                    expr,
+                    "position",
+                    option_check_method,
+                    arg_lists[1],
+                    arg_lists[0],
+                    method_spans[1],
+                )
+            },
+            [option_check_method, "rposition"]
+                if "is_some" == *option_check_method || "is_none" == *option_check_method =>
+            {
+                search_is_some::check(
+                    cx,
+                    expr,
+                    "rposition",
+                    option_check_method,
+                    arg_lists[1],
+                    arg_lists[0],
+                    method_spans[1],
+                )
             },
             ["extend", ..] => string_extend_chars::check(cx, expr, arg_lists[0]),
             ["count", "into_iter"] => iter_count::check(cx, expr, &arg_lists[1], "into_iter"),
@@ -1739,7 +1783,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                 unnecessary_filter_map::check(cx, expr, arg_lists[0]);
                 filter_map_identity::check(cx, expr, arg_lists[0], method_spans[0]);
             },
-            ["count", "map"] => suspicious_map::check(cx, expr),
+            ["count", "map"] => suspicious_map::check(cx, expr, arg_lists[1], arg_lists[0]),
             ["assume_init"] => uninit_assumed_init::check(cx, &arg_lists[0][0], expr),
             ["unwrap_or", arith @ ("checked_add" | "checked_sub" | "checked_mul")] => {
                 manual_saturating_arithmetic::check(cx, expr, &arg_lists, &arith["checked_".len()..])
@@ -1768,46 +1812,17 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
 
         match expr.kind {
             hir::ExprKind::Call(ref func, ref args) => {
-                if let hir::ExprKind::Path(path) = &func.kind {
-                    if match_qpath(path, &["from_iter"]) {
-                        from_iter_instead_of_collect::check(cx, expr, args);
-                    }
-                }
+                from_iter_instead_of_collect::check(cx, expr, args, &func.kind);
             },
             hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args, _) => {
                 or_fun_call::check(cx, expr, *method_span, &method_call.ident.as_str(), args);
                 expect_fun_call::check(cx, expr, *method_span, &method_call.ident.as_str(), args);
-
-                let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0]);
-                if args.len() == 1 && method_call.ident.name == sym::clone {
-                    clone_on_copy::check(cx, expr, &args[0], self_ty);
-                    clone_on_ref_ptr::check(cx, expr, &args[0]);
-                }
-                if args.len() == 1 && method_call.ident.name == sym!(to_string) {
-                    inefficient_to_string::check(cx, expr, &args[0], self_ty);
-                }
-
-                if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
-                    if match_def_path(cx, fn_def_id, &paths::PUSH_STR) {
-                        single_char_push_string::check(cx, expr, args);
-                    } else if match_def_path(cx, fn_def_id, &paths::INSERT_STR) {
-                        single_char_insert_string::check(cx, expr, args);
-                    }
-                }
-
-                match self_ty.kind() {
-                    ty::Ref(_, ty, _) if *ty.kind() == ty::Str => {
-                        for &(method, pos) in &PATTERN_METHODS {
-                            if method_call.ident.name.as_str() == method && args.len() > pos {
-                                single_char_pattern::check(cx, expr, &args[pos]);
-                            }
-                        }
-                    },
-                    ty::Ref(..) if method_call.ident.name == sym::into_iter => {
-                        into_iter_on_ref::check(cx, expr, self_ty, *method_span);
-                    },
-                    _ => (),
-                }
+                clone_on_copy::check(cx, expr, method_call.ident.name, args);
+                clone_on_ref_ptr::check(cx, expr, method_call.ident.name, args);
+                inefficient_to_string::check(cx, expr, method_call.ident.name, args);
+                single_char_add_str::check(cx, expr, args);
+                into_iter_on_ref::check(cx, expr, *method_span, method_call.ident.name, args);
+                single_char_pattern::check(cx, expr, method_call.ident.name, args);
             },
             hir::ExprKind::Binary(op, ref lhs, ref rhs)
                 if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne =>
@@ -1834,10 +1849,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
         let item = cx.tcx.hir().expect_item(parent);
         let self_ty = cx.tcx.type_of(item.def_id);
 
-        // if this impl block implements a trait, lint in trait definition instead
-        if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind {
-            return;
-        }
+        let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }));
 
         if_chain! {
             if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind;
@@ -1852,12 +1864,13 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
             if let Some(first_arg_ty) = first_arg_ty;
 
             then {
-                if cx.access_levels.is_exported(impl_item.hir_id()) {
+                // if this impl block implements a trait, lint in trait definition instead
+                if !implements_trait && cx.access_levels.is_exported(impl_item.hir_id()) {
                     // check missing trait implementations
                     for method_config in &TRAIT_METHODS {
                         if name == method_config.method_name &&
                             sig.decl.inputs.len() == method_config.param_count &&
-                            method_config.output_type.matches(cx, &sig.decl.output) &&
+                            method_config.output_type.matches(&sig.decl.output) &&
                             method_config.self_kind.matches(cx, self_ty, first_arg_ty) &&
                             fn_header_equals(method_config.fn_header, sig.header) &&
                             method_config.lifetime_param_cond(&impl_item)
@@ -1888,16 +1901,26 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                     item.vis.node.is_pub(),
                     self_ty,
                     first_arg_ty,
-                    first_arg.pat.span
+                    first_arg.pat.span,
+                    false
                 );
             }
         }
 
+        // if this impl block implements a trait, lint in trait definition instead
+        if implements_trait {
+            return;
+        }
+
         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 contains_ty(ret_ty, self_ty) {
+            if let Some(self_adt) = self_ty.ty_adt_def() {
+                if contains_adt_constructor(ret_ty, self_adt) {
+                    return;
+                }
+            } else if contains_ty(ret_ty, self_ty) {
                 return;
             }
 
@@ -1907,7 +1930,11 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                 for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
                     if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
                         // walk the associated type and check for Self
-                        if contains_ty(projection_predicate.ty, self_ty) {
+                        if let Some(self_adt) = self_ty.ty_adt_def() {
+                            if contains_adt_constructor(projection_predicate.ty, self_adt) {
+                                return;
+                            }
+                        } else if contains_ty(projection_predicate.ty, self_ty) {
                             return;
                         }
                     }
@@ -1944,7 +1971,8 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                     false,
                     self_ty,
                     first_arg_ty,
-                    first_arg_span
+                    first_arg_span,
+                    true
                 );
             }
         }
@@ -1969,47 +1997,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
 
     extract_msrv_attr!(LateContext);
 }
-
-fn derefs_to_slice<'tcx>(
-    cx: &LateContext<'tcx>,
-    expr: &'tcx hir::Expr<'tcx>,
-    ty: Ty<'tcx>,
-) -> Option<&'tcx hir::Expr<'tcx>> {
-    fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool {
-        match ty.kind() {
-            ty::Slice(_) => true,
-            ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
-            ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::vec_type),
-            ty::Array(_, size) => size
-                .try_eval_usize(cx.tcx, cx.param_env)
-                .map_or(false, |size| size < 32),
-            ty::Ref(_, inner, _) => may_slice(cx, inner),
-            _ => false,
-        }
-    }
-
-    if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind {
-        if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(&args[0])) {
-            Some(&args[0])
-        } else {
-            None
-        }
-    } else {
-        match ty.kind() {
-            ty::Slice(_) => Some(expr),
-            ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => Some(expr),
-            ty::Ref(_, inner, _) => {
-                if may_slice(cx, inner) {
-                    Some(expr)
-                } else {
-                    None
-                }
-            },
-            _ => None,
-        }
-    }
-}
-
 /// Used for `lint_binary_expr_with_method_call`.
 #[derive(Copy, Clone)]
 struct BinaryExprInfo<'a> {
@@ -2022,7 +2009,7 @@ struct BinaryExprInfo<'a> {
 /// Checks for the `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints.
 fn lint_binary_expr_with_method_call(cx: &LateContext<'_>, info: &mut BinaryExprInfo<'_>) {
     macro_rules! lint_with_both_lhs_and_rhs {
-        ($func:ident, $cx:expr, $info:ident) => {
+        ($func:expr, $cx:expr, $info:ident) => {
             if !$func($cx, $info) {
                 ::std::mem::swap(&mut $info.chain, &mut $info.other);
                 if $func($cx, $info) {
@@ -2032,145 +2019,10 @@ fn lint_binary_expr_with_method_call(cx: &LateContext<'_>, info: &mut BinaryExpr
         };
     }
 
-    lint_with_both_lhs_and_rhs!(lint_chars_next_cmp, cx, info);
-    lint_with_both_lhs_and_rhs!(lint_chars_last_cmp, cx, info);
-    lint_with_both_lhs_and_rhs!(lint_chars_next_cmp_with_unwrap, cx, info);
-    lint_with_both_lhs_and_rhs!(lint_chars_last_cmp_with_unwrap, cx, info);
-}
-
-/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints.
-fn lint_chars_cmp(
-    cx: &LateContext<'_>,
-    info: &BinaryExprInfo<'_>,
-    chain_methods: &[&str],
-    lint: &'static Lint,
-    suggest: &str,
-) -> bool {
-    if_chain! {
-        if let Some(args) = method_chain_args(info.chain, chain_methods);
-        if let hir::ExprKind::Call(ref fun, ref arg_char) = info.other.kind;
-        if arg_char.len() == 1;
-        if let hir::ExprKind::Path(ref qpath) = fun.kind;
-        if let Some(segment) = single_segment_path(qpath);
-        if segment.ident.name == sym::Some;
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0][0]).peel_refs();
-
-            if *self_ty.kind() != ty::Str {
-                return false;
-            }
-
-            span_lint_and_sugg(
-                cx,
-                lint,
-                info.expr.span,
-                &format!("you should use the `{}` method", suggest),
-                "like this",
-                format!("{}{}.{}({})",
-                        if info.eq { "" } else { "!" },
-                        snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
-                        suggest,
-                        snippet_with_applicability(cx, arg_char[0].span, "..", &mut applicability)),
-                applicability,
-            );
-
-            return true;
-        }
-    }
-
-    false
-}
-
-/// Checks for the `CHARS_NEXT_CMP` lint.
-fn lint_chars_next_cmp<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool {
-    lint_chars_cmp(cx, info, &["chars", "next"], CHARS_NEXT_CMP, "starts_with")
-}
-
-/// Checks for the `CHARS_LAST_CMP` lint.
-fn lint_chars_last_cmp<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool {
-    if lint_chars_cmp(cx, info, &["chars", "last"], CHARS_LAST_CMP, "ends_with") {
-        true
-    } else {
-        lint_chars_cmp(cx, info, &["chars", "next_back"], CHARS_LAST_CMP, "ends_with")
-    }
-}
-
-/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`.
-fn lint_chars_cmp_with_unwrap<'tcx>(
-    cx: &LateContext<'tcx>,
-    info: &BinaryExprInfo<'_>,
-    chain_methods: &[&str],
-    lint: &'static Lint,
-    suggest: &str,
-) -> bool {
-    if_chain! {
-        if let Some(args) = method_chain_args(info.chain, chain_methods);
-        if let hir::ExprKind::Lit(ref lit) = info.other.kind;
-        if let ast::LitKind::Char(c) = lit.node;
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_and_sugg(
-                cx,
-                lint,
-                info.expr.span,
-                &format!("you should use the `{}` method", suggest),
-                "like this",
-                format!("{}{}.{}('{}')",
-                        if info.eq { "" } else { "!" },
-                        snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
-                        suggest,
-                        c),
-                applicability,
-            );
-
-            true
-        } else {
-            false
-        }
-    }
-}
-
-/// Checks for the `CHARS_NEXT_CMP` lint with `unwrap()`.
-fn lint_chars_next_cmp_with_unwrap<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool {
-    lint_chars_cmp_with_unwrap(cx, info, &["chars", "next", "unwrap"], CHARS_NEXT_CMP, "starts_with")
-}
-
-/// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`.
-fn lint_chars_last_cmp_with_unwrap<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool {
-    if lint_chars_cmp_with_unwrap(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") {
-        true
-    } else {
-        lint_chars_cmp_with_unwrap(cx, info, &["chars", "next_back", "unwrap"], CHARS_LAST_CMP, "ends_with")
-    }
-}
-
-fn get_hint_if_single_char_arg(
-    cx: &LateContext<'_>,
-    arg: &hir::Expr<'_>,
-    applicability: &mut Applicability,
-) -> Option<String> {
-    if_chain! {
-        if let hir::ExprKind::Lit(lit) = &arg.kind;
-        if let ast::LitKind::Str(r, style) = lit.node;
-        let string = r.as_str();
-        if string.chars().count() == 1;
-        then {
-            let snip = snippet_with_applicability(cx, arg.span, &string, applicability);
-            let ch = if let ast::StrStyle::Raw(nhash) = style {
-                let nhash = nhash as usize;
-                // for raw string: r##"a"##
-                &snip[(nhash + 2)..(snip.len() - 1 - nhash)]
-            } else {
-                // for regular string: "a"
-                &snip[1..(snip.len() - 1)]
-            };
-            let hint = format!("'{}'", if ch == "'" { "\\'" } else { ch });
-            Some(hint)
-        } else {
-            None
-        }
-    }
+    lint_with_both_lhs_and_rhs!(chars_next_cmp::check, cx, info);
+    lint_with_both_lhs_and_rhs!(chars_last_cmp::check, cx, info);
+    lint_with_both_lhs_and_rhs!(chars_next_cmp_with_unwrap::check, cx, info);
+    lint_with_both_lhs_and_rhs!(chars_last_cmp_with_unwrap::check, cx, info);
 }
 
 const FN_HEADER: hir::FnHeader = hir::FnHeader {
@@ -2336,10 +2188,10 @@ impl SelfKind {
     #[must_use]
     fn description(self) -> &'static str {
         match self {
-            Self::Value => "self by value",
-            Self::Ref => "self by reference",
-            Self::RefMut => "self by mutable reference",
-            Self::No => "no self",
+            Self::Value => "`self` by value",
+            Self::Ref => "`self` by reference",
+            Self::RefMut => "`self` by mutable reference",
+            Self::No => "no `self`",
         }
     }
 }
@@ -2353,8 +2205,8 @@ enum OutType {
 }
 
 impl OutType {
-    fn matches(self, cx: &LateContext<'_>, ty: &hir::FnRetTy<'_>) -> bool {
-        let is_unit = |ty: &hir::Ty<'_>| SpanlessEq::new(cx).eq_ty_kind(&ty.kind, &hir::TyKind::Tup(&[]));
+    fn matches(self, ty: &hir::FnRetTy<'_>) -> bool {
+        let is_unit = |ty: &hir::Ty<'_>| matches!(ty.kind, hir::TyKind::Tup(&[]));
         match (self, ty) {
             (Self::Unit, &hir::FnRetTy::DefaultReturn(_)) => true,
             (Self::Unit, &hir::FnRetTy::Return(ref ty)) if is_unit(ty) => true,
@@ -2367,8 +2219,8 @@ impl OutType {
 }
 
 fn is_bool(ty: &hir::Ty<'_>) -> bool {
-    if let hir::TyKind::Path(ref p) = ty.kind {
-        match_qpath(p, &["bool"])
+    if let hir::TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
+        matches!(path.res, Res::PrimTy(PrimTy::Bool))
     } else {
         false
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs b/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs
index c1706cc7cc7..e6ce9cac397 100644
--- a/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs
@@ -1,4 +1,5 @@
-use crate::utils::{implements_trait, is_type_diagnostic_item, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
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 89067dbfe0e..d11ede080dc 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
@@ -1,7 +1,7 @@
-use crate::utils::{
-    is_type_diagnostic_item, match_def_path, meets_msrv, path_to_local_id, paths, remove_blocks, snippet,
-    span_lint_and_sugg,
-};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{match_def_path, meets_msrv, path_to_local_id, paths, remove_blocks};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
index 64f6ebc5062..d93db2c22e4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
@@ -1,4 +1,7 @@
-use crate::utils::{is_type_diagnostic_item, match_qpath, paths, snippet, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{match_qpath, paths};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
index 7cdd49bbf03..e252abc177a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -1,5 +1,8 @@
-use crate::utils::{differing_macro_contexts, snippet_with_applicability, span_lint_and_then};
-use crate::utils::{is_copy, is_type_diagnostic_item};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::differing_macro_contexts;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::is_copy;
+use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_path, NestedVisitorMap, Visitor};
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 5f7fc431d22..89dedc5f0d8 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
@@ -1,11 +1,12 @@
-use crate::utils::eager_or_lazy::is_lazyness_candidate;
-use crate::utils::{
-    contains_return, get_trait_def_id, implements_trait, is_type_diagnostic_item, last_path_segment, match_type, paths,
-    snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint_and_sugg,
-};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::eager_or_lazy::is_lazyness_candidate;
+use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_macro_callsite};
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, match_type};
+use clippy_utils::{contains_return, get_trait_def_id, last_path_segment, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::{BlockCheckMode, UnsafeSource};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::source_map::Span;
@@ -90,7 +91,7 @@ pub(super) fn check<'tcx>(
                 let ty = cx.typeck_results().expr_ty(&args[0]).peel_refs();
 
                 match ty.kind() {
-                    ty::Slice(_) | ty::Array(_, _) => return,
+                    ty::Slice(_) | ty::Array(_, _) | ty::Str => return,
                     _ => (),
                 }
 
@@ -167,7 +168,16 @@ pub(super) fn check<'tcx>(
             hir::ExprKind::Index(..) | hir::ExprKind::MethodCall(..) => {
                 check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None);
             },
-            _ => {},
+            hir::ExprKind::Block(block, _) => {
+                if let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules {
+                    if let Some(block_expr) = block.expr {
+                        if let hir::ExprKind::MethodCall(..) = block_expr.kind {
+                            check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None);
+                        }
+                    }
+                }
+            },
+            _ => (),
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
index e9e65443220..de7d168295f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
@@ -1,7 +1,7 @@
-use crate::utils::{
-    is_type_diagnostic_item, match_trait_method, paths, snippet, snippet_with_applicability, span_lint_and_help,
-    span_lint_and_sugg, strip_pat_refs,
-};
+use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::source::{snippet, snippet_with_applicability};
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{is_trait_method, strip_pat_refs};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -14,22 +14,23 @@ use rustc_span::symbol::sym;
 use super::SEARCH_IS_SOME;
 
 /// lint searching an Iterator followed by `is_some()`
-/// or calling `find()` on a string followed by `is_some()`
+/// or calling `find()` on a string followed by `is_some()` or `is_none()`
+#[allow(clippy::too_many_lines)]
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx hir::Expr<'_>,
     search_method: &str,
+    option_check_method: &str,
     search_args: &'tcx [hir::Expr<'_>],
     is_some_args: &'tcx [hir::Expr<'_>],
     method_span: Span,
 ) {
     // lint if caller of search is an Iterator
-    if match_trait_method(cx, &is_some_args[0], &paths::ITERATOR) {
+    if is_trait_method(cx, &is_some_args[0], sym::Iterator) {
         let msg = format!(
-            "called `is_some()` after searching an `Iterator` with `{}`",
-            search_method
+            "called `{}()` after searching an `Iterator` with `{}`",
+            option_check_method, search_method
         );
-        let hint = "this is more succinctly expressed by calling `any()`";
         let search_snippet = snippet(cx, search_args[1].span, "..");
         if search_snippet.lines().count() <= 1 {
             // suggest `any(|x| ..)` instead of `any(|&x| ..)` for `find(|&x| ..).is_some()`
@@ -53,20 +54,49 @@ pub(super) fn check<'tcx>(
                 }
             };
             // add note if not multi-line
-            span_lint_and_sugg(
-                cx,
-                SEARCH_IS_SOME,
-                method_span.with_hi(expr.span.hi()),
-                &msg,
-                "use `any()` instead",
-                format!(
-                    "any({})",
-                    any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
-                ),
-                Applicability::MachineApplicable,
-            );
+            match option_check_method {
+                "is_some" => {
+                    span_lint_and_sugg(
+                        cx,
+                        SEARCH_IS_SOME,
+                        method_span.with_hi(expr.span.hi()),
+                        &msg,
+                        "use `any()` instead",
+                        format!(
+                            "any({})",
+                            any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
+                        ),
+                        Applicability::MachineApplicable,
+                    );
+                },
+                "is_none" => {
+                    let iter = snippet(cx, search_args[0].span, "..");
+                    span_lint_and_sugg(
+                        cx,
+                        SEARCH_IS_SOME,
+                        expr.span,
+                        &msg,
+                        "use `!_.any()` instead",
+                        format!(
+                            "!{}.any({})",
+                            iter,
+                            any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
+                        ),
+                        Applicability::MachineApplicable,
+                    );
+                },
+                _ => (),
+            }
         } else {
-            span_lint_and_help(cx, SEARCH_IS_SOME, expr.span, &msg, None, hint);
+            let hint = format!(
+                "this is more succinctly expressed by calling `any()`{}",
+                if option_check_method == "is_none" {
+                    " with negation"
+                } else {
+                    ""
+                }
+            );
+            span_lint_and_help(cx, SEARCH_IS_SOME, expr.span, &msg, None, &hint);
         }
     }
     // lint if `find()` is called by `String` or `&str`
@@ -83,18 +113,37 @@ pub(super) fn check<'tcx>(
             if is_string_or_str_slice(&search_args[0]);
             if is_string_or_str_slice(&search_args[1]);
             then {
-                let msg = "called `is_some()` after calling `find()` on a string";
-                let mut applicability = Applicability::MachineApplicable;
-                let find_arg = snippet_with_applicability(cx, search_args[1].span, "..", &mut applicability);
-                span_lint_and_sugg(
-                    cx,
-                    SEARCH_IS_SOME,
-                    method_span.with_hi(expr.span.hi()),
-                    msg,
-                    "use `contains()` instead",
-                    format!("contains({})", find_arg),
-                    applicability,
-                );
+                let msg = format!("called `{}()` after calling `find()` on a string", option_check_method);
+                match option_check_method {
+                    "is_some" => {
+                        let mut applicability = Applicability::MachineApplicable;
+                        let find_arg = snippet_with_applicability(cx, search_args[1].span, "..", &mut applicability);
+                        span_lint_and_sugg(
+                            cx,
+                            SEARCH_IS_SOME,
+                            method_span.with_hi(expr.span.hi()),
+                            &msg,
+                            "use `contains()` instead",
+                            format!("contains({})", find_arg),
+                            applicability,
+                        );
+                    },
+                    "is_none" => {
+                        let string = snippet(cx, search_args[0].span, "..");
+                        let mut applicability = Applicability::MachineApplicable;
+                        let find_arg = snippet_with_applicability(cx, search_args[1].span, "..", &mut applicability);
+                        span_lint_and_sugg(
+                            cx,
+                            SEARCH_IS_SOME,
+                            expr.span,
+                            &msg,
+                            "use `!_.contains()` instead",
+                            format!("!{}.contains({})", string, find_arg),
+                            applicability,
+                        );
+                    },
+                    _ => (),
+                }
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_add_str.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_add_str.rs
new file mode 100644
index 00000000000..9a5fabcf7cd
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/single_char_add_str.rs
@@ -0,0 +1,14 @@
+use crate::methods::{single_char_insert_string, single_char_push_string};
+use clippy_utils::{match_def_path, paths};
+use rustc_hir as hir;
+use rustc_lint::LateContext;
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
+    if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
+        if match_def_path(cx, fn_def_id, &paths::PUSH_STR) {
+            single_char_push_string::check(cx, expr, args);
+        } else if match_def_path(cx, fn_def_id, &paths::INSERT_STR) {
+            single_char_insert_string::check(cx, expr, args);
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs
index 0ce8b66978d..6cdc954c03b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs
@@ -1,5 +1,6 @@
-use crate::methods::get_hint_if_single_char_arg;
-use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
+use super::utils::get_hint_if_single_char_arg;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs
index 61cbc9d2f0a..f4090c7c617 100644
--- a/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs
@@ -1,23 +1,35 @@
-use crate::methods::get_hint_if_single_char_arg;
-use crate::utils::span_lint_and_sugg;
+use super::utils::get_hint_if_single_char_arg;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
+use rustc_middle::ty;
+use rustc_span::symbol::Symbol;
 
 use super::SINGLE_CHAR_PATTERN;
 
 /// lint for length-1 `str`s for methods in `PATTERN_METHODS`
-pub(super) fn check(cx: &LateContext<'_>, _expr: &hir::Expr<'_>, arg: &hir::Expr<'_>) {
-    let mut applicability = Applicability::MachineApplicable;
-    if let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability) {
-        span_lint_and_sugg(
-            cx,
-            SINGLE_CHAR_PATTERN,
-            arg.span,
-            "single-character string constant used as pattern",
-            "try using a `char` instead",
-            hint,
-            applicability,
-        );
+pub(super) fn check(cx: &LateContext<'_>, _expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) {
+    for &(method, pos) in &crate::methods::PATTERN_METHODS {
+        if_chain! {
+            if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(&args[0]).kind();
+            if *ty.kind() == ty::Str;
+            if method_name.as_str() == method && args.len() > pos;
+            let arg = &args[pos];
+            let mut applicability = Applicability::MachineApplicable;
+            if let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability);
+            then {
+                span_lint_and_sugg(
+                    cx,
+                    SINGLE_CHAR_PATTERN,
+                    arg.span,
+                    "single-character string constant used as pattern",
+                    "try using a `char` instead",
+                    hint,
+                    applicability,
+                );
+            }
+        }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs
index deacc70b713..0237d39cbdb 100644
--- a/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs
@@ -1,5 +1,6 @@
-use crate::methods::get_hint_if_single_char_arg;
-use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
+use super::utils::get_hint_if_single_char_arg;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/methods/skip_while_next.rs b/src/tools/clippy/clippy_lints/src/methods/skip_while_next.rs
index 8ba6ae95200..3db83785b59 100644
--- a/src/tools/clippy/clippy_lints/src/methods/skip_while_next.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/skip_while_next.rs
@@ -1,13 +1,15 @@
-use crate::utils::{match_trait_method, paths, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::is_trait_method;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
+use rustc_span::sym;
 
 use super::SKIP_WHILE_NEXT;
 
 /// lint use of `skip_while().next()` for `Iterators`
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, _skip_while_args: &'tcx [hir::Expr<'_>]) {
     // lint if caller of `.skip_while().next()` is an Iterator
-    if match_trait_method(cx, expr, &paths::ITERATOR) {
+    if is_trait_method(cx, expr, sym::Iterator) {
         span_lint_and_help(
             cx,
             SKIP_WHILE_NEXT,
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 0a08ea26175..5c688ac5621 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
@@ -1,4 +1,7 @@
-use crate::utils::{is_type_diagnostic_item, method_chain_args, snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::method_chain_args;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -9,34 +12,35 @@ use super::STRING_EXTEND_CHARS;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
     let obj_ty = cx.typeck_results().expr_ty(&args[0]).peel_refs();
-    if is_type_diagnostic_item(cx, obj_ty, sym::string_type) {
-        let arg = &args[1];
-        if let Some(arglists) = method_chain_args(arg, &["chars"]) {
-            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 {
-                ""
-            } else if is_type_diagnostic_item(cx, self_ty, sym::string_type) {
-                "&"
-            } else {
-                return;
-            };
+    if !is_type_diagnostic_item(cx, obj_ty, sym::string_type) {
+        return;
+    }
+    let arg = &args[1];
+    if let Some(arglists) = method_chain_args(arg, &["chars"]) {
+        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 {
+            ""
+        } else if is_type_diagnostic_item(cx, self_ty, sym::string_type) {
+            "&"
+        } else {
+            return;
+        };
 
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_and_sugg(
-                cx,
-                STRING_EXTEND_CHARS,
-                expr.span,
-                "calling `.extend(_.chars())`",
-                "try this",
-                format!(
-                    "{}.push_str({}{})",
-                    snippet_with_applicability(cx, args[0].span, "..", &mut applicability),
-                    ref_str,
-                    snippet_with_applicability(cx, target.span, "..", &mut applicability)
-                ),
-                applicability,
-            );
-        }
+        let mut applicability = Applicability::MachineApplicable;
+        span_lint_and_sugg(
+            cx,
+            STRING_EXTEND_CHARS,
+            expr.span,
+            "calling `.extend(_.chars())`",
+            "try this",
+            format!(
+                "{}.push_str({}{})",
+                snippet_with_applicability(cx, args[0].span, "..", &mut applicability),
+                ref_str,
+                snippet_with_applicability(cx, target.span, "..", &mut applicability)
+            ),
+            applicability,
+        );
     }
 }
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 e135a826dc4..7015bd54c35 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs
@@ -1,16 +1,42 @@
-use crate::utils::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::usage::mutated_variables;
+use clippy_utils::{expr_or_init, is_trait_method};
+use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
+use rustc_span::sym;
 
 use super::SUSPICIOUS_MAP;
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
-    span_lint_and_help(
-        cx,
-        SUSPICIOUS_MAP,
-        expr.span,
-        "this call to `map()` won't have an effect on the call to `count()`",
-        None,
-        "make sure you did not confuse `map` with `filter` or `for_each`",
-    );
+pub fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &hir::Expr<'_>,
+    map_args: &[hir::Expr<'_>],
+    count_args: &[hir::Expr<'_>],
+) {
+    if_chain! {
+        if let [count_recv] = count_args;
+        if let [_, map_arg] = map_args;
+        if is_trait_method(cx, count_recv, sym::Iterator);
+        let closure = expr_or_init(cx, map_arg);
+        if let Some(body_id) = cx.tcx.hir().maybe_body_owned_by(closure.hir_id);
+        let closure_body = cx.tcx.hir().body(body_id);
+        if !cx.typeck_results().expr_ty(&closure_body.value).is_unit();
+        then {
+            if let Some(map_mutated_vars) = mutated_variables(&closure_body.value, cx) {
+                // A variable is used mutably inside of the closure. Suppress the lint.
+                if !map_mutated_vars.is_empty() {
+                    return;
+                }
+            }
+            span_lint_and_help(
+                cx,
+                SUSPICIOUS_MAP,
+                expr.span,
+                "this call to `map()` won't have an effect on the call to `count()`",
+                None,
+                "make sure you did not confuse `map` with `filter` or `for_each`",
+            );
+        }
+    }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/uninit_assumed_init.rs b/src/tools/clippy/clippy_lints/src/methods/uninit_assumed_init.rs
index 798b66192c8..f2f6ef4be6c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/uninit_assumed_init.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/uninit_assumed_init.rs
@@ -1,4 +1,5 @@
-use crate::utils::{match_def_path, match_qpath, paths, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{match_def_path, match_qpath, paths};
 use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
index 12b2cf0a165..48d905ab833 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
@@ -1,16 +1,17 @@
-use crate::utils::usage::mutated_variables;
-use crate::utils::{match_qpath, match_trait_method, path_to_local_id, paths, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::usage::mutated_variables;
+use clippy_utils::{is_trait_method, match_qpath, path_to_local_id, paths};
+use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
 use rustc_lint::LateContext;
 use rustc_middle::hir::map::Map;
-
-use if_chain::if_chain;
+use rustc_span::sym;
 
 use super::UNNECESSARY_FILTER_MAP;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
-    if !match_trait_method(cx, expr, &paths::ITERATOR) {
+    if !is_trait_method(cx, expr, sym::Iterator) {
         return;
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
index a26443f4ee9..1268fd4bda9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
@@ -1,14 +1,13 @@
-use crate::utils::{
-    match_trait_method, path_to_local_id, paths, remove_blocks, snippet_with_applicability, span_lint_and_sugg,
-    strip_pat_refs,
-};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::{is_trait_method, path_to_local_id, remove_blocks, strip_pat_refs};
 use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::PatKind;
 use rustc_lint::LateContext;
-use rustc_span::source_map::Span;
+use rustc_span::{source_map::Span, sym};
 
 use super::UNNECESSARY_FOLD;
 
@@ -71,7 +70,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, fold_args: &[hir
     }
 
     // Check that this is a call to Iterator::fold rather than just some function called fold
-    if !match_trait_method(cx, expr, &paths::ITERATOR) {
+    if !is_trait_method(cx, expr, sym::Iterator) {
         return;
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
index a17259d697f..a86185bf0a6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
@@ -1,5 +1,7 @@
-use crate::utils::{eager_or_lazy, usage};
-use crate::utils::{is_type_diagnostic_item, snippet, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{eager_or_lazy, usage};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
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 094c3fc45c4..2f5806115bd 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs
@@ -1,4 +1,5 @@
-use crate::utils::{is_type_diagnostic_item, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_span::sym;
diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
index e4554f8d489..b5505af0f7e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
@@ -1,6 +1,7 @@
-use crate::utils::{
-    get_parent_expr, match_trait_method, paths, snippet_with_applicability, span_lint_and_sugg, walk_ptrs_ty_depth,
-};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::walk_ptrs_ty_depth;
+use clippy_utils::{get_parent_expr, match_trait_method, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs
new file mode 100644
index 00000000000..ac6b55396da
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs
@@ -0,0 +1,77 @@
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::is_type_diagnostic_item;
+use if_chain::if_chain;
+use rustc_ast::ast;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_lint::LateContext;
+use rustc_middle::ty::{self, Ty};
+use rustc_span::symbol::sym;
+
+pub(super) fn derefs_to_slice<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx hir::Expr<'tcx>,
+    ty: Ty<'tcx>,
+) -> Option<&'tcx hir::Expr<'tcx>> {
+    fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool {
+        match ty.kind() {
+            ty::Slice(_) => true,
+            ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
+            ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::vec_type),
+            ty::Array(_, size) => size
+                .try_eval_usize(cx.tcx, cx.param_env)
+                .map_or(false, |size| size < 32),
+            ty::Ref(_, inner, _) => may_slice(cx, inner),
+            _ => false,
+        }
+    }
+
+    if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind {
+        if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(&args[0])) {
+            Some(&args[0])
+        } else {
+            None
+        }
+    } else {
+        match ty.kind() {
+            ty::Slice(_) => Some(expr),
+            ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => Some(expr),
+            ty::Ref(_, inner, _) => {
+                if may_slice(cx, inner) {
+                    Some(expr)
+                } else {
+                    None
+                }
+            },
+            _ => None,
+        }
+    }
+}
+
+pub(super) fn get_hint_if_single_char_arg(
+    cx: &LateContext<'_>,
+    arg: &hir::Expr<'_>,
+    applicability: &mut Applicability,
+) -> Option<String> {
+    if_chain! {
+        if let hir::ExprKind::Lit(lit) = &arg.kind;
+        if let ast::LitKind::Str(r, style) = lit.node;
+        let string = r.as_str();
+        if string.chars().count() == 1;
+        then {
+            let snip = snippet_with_applicability(cx, arg.span, &string, applicability);
+            let ch = if let ast::StrStyle::Raw(nhash) = style {
+                let nhash = nhash as usize;
+                // for raw string: r##"a"##
+                &snip[(nhash + 2)..(snip.len() - 1 - nhash)]
+            } else {
+                // for regular string: "a"
+                &snip[1..(snip.len() - 1)]
+            };
+            let hint = format!("'{}'", if ch == "'" { "\\'" } else { ch });
+            Some(hint)
+        } else {
+            None
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs b/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
index 90fab577436..59e683aa9a7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
@@ -1,5 +1,6 @@
 use crate::methods::SelfKind;
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::ty::is_copy;
 use rustc_lint::LateContext;
 use rustc_middle::ty::TyS;
 use rustc_span::source_map::Span;
@@ -9,26 +10,40 @@ use super::WRONG_PUB_SELF_CONVENTION;
 use super::WRONG_SELF_CONVENTION;
 
 #[rustfmt::skip]
-const CONVENTIONS: [(Convention, &[SelfKind]); 7] = [
-    (Convention::Eq("new"), &[SelfKind::No]),
-    (Convention::StartsWith("as_"), &[SelfKind::Ref, SelfKind::RefMut]),
-    (Convention::StartsWith("from_"), &[SelfKind::No]),
-    (Convention::StartsWith("into_"), &[SelfKind::Value]),
-    (Convention::StartsWith("is_"), &[SelfKind::Ref, SelfKind::No]),
-    (Convention::Eq("to_mut"), &[SelfKind::RefMut]),
-    (Convention::StartsWith("to_"), &[SelfKind::Ref]),
+const CONVENTIONS: [(&[Convention], &[SelfKind]); 9] = [
+    (&[Convention::Eq("new")], &[SelfKind::No]),
+    (&[Convention::StartsWith("as_")], &[SelfKind::Ref, SelfKind::RefMut]),
+    (&[Convention::StartsWith("from_")], &[SelfKind::No]),
+    (&[Convention::StartsWith("into_")], &[SelfKind::Value]),
+    (&[Convention::StartsWith("is_")], &[SelfKind::Ref, SelfKind::No]),
+    (&[Convention::Eq("to_mut")], &[SelfKind::RefMut]),
+    (&[Convention::StartsWith("to_"), Convention::EndsWith("_mut")], &[SelfKind::RefMut]),
+
+    // Conversion using `to_` can use borrowed (non-Copy types) or owned (Copy types).
+    // Source: https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv
+    (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(false), Convention::ImplementsTrait(false)], &[SelfKind::Ref]),
+    (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(true), Convention::ImplementsTrait(false)], &[SelfKind::Value]),
 ];
+
 enum Convention {
     Eq(&'static str),
     StartsWith(&'static str),
+    EndsWith(&'static str),
+    NotEndsWith(&'static str),
+    IsSelfTypeCopy(bool),
+    ImplementsTrait(bool),
 }
 
 impl Convention {
     #[must_use]
-    fn check(&self, other: &str) -> bool {
+    fn check<'tcx>(&self, cx: &LateContext<'tcx>, self_ty: &'tcx TyS<'tcx>, other: &str, is_trait_def: bool) -> bool {
         match *self {
             Self::Eq(this) => this == other,
             Self::StartsWith(this) => other.starts_with(this) && this != other,
+            Self::EndsWith(this) => other.ends_with(this) && this != other,
+            Self::NotEndsWith(this) => !Self::EndsWith(this).check(cx, self_ty, other, is_trait_def),
+            Self::IsSelfTypeCopy(is_true) => is_true == is_copy(cx, self_ty),
+            Self::ImplementsTrait(is_true) => is_true == is_trait_def,
         }
     }
 }
@@ -36,8 +51,17 @@ impl Convention {
 impl fmt::Display for Convention {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
         match *self {
-            Self::Eq(this) => this.fmt(f),
-            Self::StartsWith(this) => this.fmt(f).and_then(|_| '*'.fmt(f)),
+            Self::Eq(this) => format!("`{}`", this).fmt(f),
+            Self::StartsWith(this) => format!("`{}*`", this).fmt(f),
+            Self::EndsWith(this) => format!("`*{}`", this).fmt(f),
+            Self::NotEndsWith(this) => format!("`~{}`", this).fmt(f),
+            Self::IsSelfTypeCopy(is_true) => {
+                format!("`self` type is{} `Copy`", if is_true { "" } else { " not" }).fmt(f)
+            },
+            Self::ImplementsTrait(is_true) => {
+                let (negation, s_suffix) = if is_true { ("", "s") } else { (" does not", "") };
+                format!("Method{} implement{} a trait", negation, s_suffix).fmt(f)
+            },
         }
     }
 }
@@ -49,27 +73,62 @@ pub(super) fn check<'tcx>(
     self_ty: &'tcx TyS<'tcx>,
     first_arg_ty: &'tcx TyS<'tcx>,
     first_arg_span: Span,
+    is_trait_item: bool,
 ) {
     let lint = if is_pub {
         WRONG_PUB_SELF_CONVENTION
     } else {
         WRONG_SELF_CONVENTION
     };
-    if let Some((ref conv, self_kinds)) = &CONVENTIONS.iter().find(|(ref conv, _)| conv.check(item_name)) {
+    if let Some((conventions, self_kinds)) = &CONVENTIONS.iter().find(|(convs, _)| {
+        convs
+            .iter()
+            .all(|conv| conv.check(cx, self_ty, item_name, is_trait_item))
+    }) {
         if !self_kinds.iter().any(|k| k.matches(cx, self_ty, first_arg_ty)) {
-            span_lint(
+            let suggestion = {
+                if conventions.len() > 1 {
+                    // Don't mention `NotEndsWith` when there is also `StartsWith` convention present
+                    let cut_ends_with_conv = conventions.iter().any(|conv| matches!(conv, Convention::StartsWith(_)))
+                        && conventions
+                            .iter()
+                            .any(|conv| matches!(conv, Convention::NotEndsWith(_)));
+
+                    let s = conventions
+                        .iter()
+                        .filter_map(|conv| {
+                            if (cut_ends_with_conv && matches!(conv, Convention::NotEndsWith(_)))
+                                || matches!(conv, Convention::ImplementsTrait(_))
+                            {
+                                None
+                            } else {
+                                Some(conv.to_string())
+                            }
+                        })
+                        .collect::<Vec<_>>()
+                        .join(" and ");
+
+                    format!("methods with the following characteristics: ({})", &s)
+                } else {
+                    format!("methods called {}", &conventions[0])
+                }
+            };
+
+            span_lint_and_help(
                 cx,
                 lint,
                 first_arg_span,
                 &format!(
-                    "methods called `{}` usually take {}; consider choosing a less ambiguous name",
-                    conv,
+                    "{} usually take {}",
+                    suggestion,
                     &self_kinds
                         .iter()
                         .map(|k| k.description())
                         .collect::<Vec<_>>()
                         .join(" or ")
                 ),
+                None,
+                "consider choosing a less ambiguous name",
             );
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs b/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs
index f1335726736..9f6a7c4db17 100644
--- a/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs
@@ -1,4 +1,4 @@
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/minmax.rs b/src/tools/clippy/clippy_lints/src/minmax.rs
index 8d0c3b8e0fe..776f4c7b741 100644
--- a/src/tools/clippy/clippy_lints/src/minmax.rs
+++ b/src/tools/clippy/clippy_lints/src/minmax.rs
@@ -1,5 +1,6 @@
 use crate::consts::{constant_simple, Constant};
-use crate::utils::{match_def_path, match_trait_method, paths, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{match_def_path, match_trait_method, paths};
 use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index acdc245456b..026ea50936a 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -1,3 +1,6 @@
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then};
+use clippy_utils::source::{snippet, snippet_opt};
+use clippy_utils::ty::implements_trait;
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
@@ -15,11 +18,10 @@ use rustc_span::source_map::{ExpnKind, Span};
 use rustc_span::symbol::sym;
 
 use crate::consts::{constant, Constant};
-use crate::utils::sugg::Sugg;
-use crate::utils::{
-    get_item_name, get_parent_expr, higher, implements_trait, in_constant, is_diagnostic_assoc_item, is_integer_const,
-    iter_input_pats, last_path_segment, match_qpath, snippet, snippet_opt, span_lint, span_lint_and_sugg,
-    span_lint_and_then, span_lint_hir_and_then, unsext, SpanlessEq,
+use clippy_utils::sugg::Sugg;
+use clippy_utils::{
+    get_item_name, get_parent_expr, higher, in_constant, is_diagnostic_assoc_item, is_integer_const, iter_input_pats,
+    last_path_segment, match_qpath, unsext, SpanlessEq,
 };
 
 declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/misc_early.rs b/src/tools/clippy/clippy_lints/src/misc_early.rs
index 84a0df92f5b..3c6a7071c24 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early.rs
@@ -1,4 +1,5 @@
-use crate::utils::{snippet_opt, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::source::snippet_opt;
 use rustc_ast::ast::{
     BindingMode, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability,
     NodeId, Pat, PatKind, UnOp,
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index b0998a80128..23554669d97 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -1,7 +1,7 @@
-use crate::utils::qualify_min_const_fn::is_min_const_fn;
-use crate::utils::{
-    fn_has_unsatisfiable_preds, has_drop, is_entrypoint_fn, meets_msrv, span_lint, trait_ref_of_method,
-};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::qualify_min_const_fn::is_min_const_fn;
+use clippy_utils::ty::has_drop;
+use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, meets_msrv, trait_ref_of_method};
 use rustc_hir as hir;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId};
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index 985a66b6cfc..21b4983a1af 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -5,7 +5,7 @@
 // [`missing_doc`]: https://github.com/rust-lang/rust/blob/cf9cf7c923eb01146971429044f216a3ca905e06/compiler/rustc_lint/src/builtin.rs#L415
 //
 
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use if_chain::if_chain;
 use rustc_ast::ast::{self, MetaItem, MetaItemKind};
 use rustc_ast::attr;
@@ -95,7 +95,7 @@ impl MissingDoc {
 
         let has_doc = attrs
             .iter()
-            .any(|a| a.is_doc_comment() || a.doc_str().is_some() || a.is_value_str() || Self::has_include(a.meta()));
+            .any(|a| a.is_doc_comment() || a.doc_str().is_some() || a.value_str().is_some() || Self::has_include(a.meta()));
         if !has_doc {
             span_lint(
                 cx,
@@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
 
     fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) {
         let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID);
-        self.check_missing_docs_attrs(cx, attrs, krate.item.span, "the", "crate");
+        self.check_missing_docs_attrs(cx, attrs, krate.item.inner, "the", "crate");
     }
 
     fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index da59c820999..dd4488f3f02 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -1,4 +1,4 @@
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast;
 use rustc_hir as hir;
 use rustc_lint::{self, LateContext, LateLintPass, LintContext};
diff --git a/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs
index da3ae1d652f..6a52de4f713 100644
--- a/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs
@@ -1,5 +1,6 @@
 use crate::consts::{constant, Constant};
-use crate::utils::{sext, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sext;
 use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs b/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs
index c1773cef7a8..584daa5e119 100644
--- a/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs
+++ b/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs
@@ -1,6 +1,7 @@
 //! lint on multiple versions of a crate being used
 
-use crate::utils::{run_lints, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::run_lints;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::{Crate, CRATE_HIR_ID};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs
index 908b7bb7ce0..4d3dff36a20 100644
--- a/src/tools/clippy/clippy_lints/src/mut_key.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_key.rs
@@ -1,10 +1,12 @@
-use crate::utils::{match_def_path, paths, span_lint, trait_ref_of_method};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{match_def_path, paths, trait_ref_of_method};
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::TypeFoldable;
 use rustc_middle::ty::{Adt, Array, RawPtr, Ref, Slice, Tuple, Ty, TypeAndMut};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
+use std::iter;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for sets/maps with mutable key types.
@@ -86,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType {
 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 decl.inputs.iter().zip(fn_sig.inputs().skip_binder().iter()) {
+    for (hir_ty, ty) in iter::zip(decl.inputs, fn_sig.inputs().skip_binder()) {
         check_ty(cx, hir_ty.span, ty);
     }
     check_ty(cx, decl.output.span(), cx.tcx.erase_late_bound_regions(fn_sig.output()));
diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs
index d7239b328bb..ef33e41a5fa 100644
--- a/src/tools/clippy/clippy_lints/src/mut_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs
@@ -1,4 +1,5 @@
-use crate::utils::{higher, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::higher;
 use rustc_hir as hir;
 use rustc_hir::intravisit;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
diff --git a/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs b/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs
index df1cecb328c..b9ba74c7d02 100644
--- a/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs
@@ -1,4 +1,5 @@
-use crate::utils::{is_type_diagnostic_item, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Mutability};
diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs
index 3f0b765df15..05457e80d52 100644
--- a/src/tools/clippy/clippy_lints/src/mut_reference.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs
@@ -1,9 +1,10 @@
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use std::iter;
 
 declare_clippy_lint! {
     /// **What it does:** Detects passing a mutable reference to a function that only
@@ -64,7 +65,7 @@ fn check_arguments<'tcx>(
     match type_definition.kind() {
         ty::FnDef(..) | ty::FnPtr(_) => {
             let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs();
-            for (argument, parameter) in arguments.iter().zip(parameters.iter()) {
+            for (argument, parameter) in iter::zip(arguments, parameters) {
                 match parameter.kind() {
                     ty::Ref(_, _, Mutability::Not)
                     | ty::RawPtr(ty::TypeAndMut {
diff --git a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
index 9caacb5db7c..7dfe12cd4eb 100644
--- a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
+++ b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
@@ -1,4 +1,5 @@
-use crate::utils::{higher, is_direct_expn_of, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{higher, is_direct_expn_of};
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
 use rustc_hir::{BorrowKind, Expr, ExprKind, MatchSource, Mutability};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
index 40b236493a3..354e2c3fb74 100644
--- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
+++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
@@ -2,7 +2,8 @@
 //!
 //! This lint is **warn** by default
 
-use crate::utils::{is_type_diagnostic_item, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_hir::Expr;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, Ty};
diff --git a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs
index 7687962bdd9..3e2b2782ed5 100644
--- a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs
@@ -1,4 +1,5 @@
-use crate::utils::{in_macro, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::in_macro;
 use if_chain::if_chain;
 use rustc_ast::ast::{BindingMode, Lifetime, Mutability, Param, PatKind, Path, TyKind};
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs
index f283ff1715f..db7b3423ad9 100644
--- a/src/tools/clippy/clippy_lints/src/needless_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs
@@ -2,8 +2,10 @@
 //!
 //! This lint is **warn** by default
 
-use crate::utils::sugg::Sugg;
-use crate::utils::{is_expn_of, parent_node_is_if_expr, snippet_with_applicability, span_lint, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::sugg::Sugg;
+use clippy_utils::{is_expn_of, parent_node_is_if_expr};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp};
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrow.rs b/src/tools/clippy/clippy_lints/src/needless_borrow.rs
index 1aadcfd87b6..79d84da2dfc 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrow.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrow.rs
@@ -2,7 +2,9 @@
 //!
 //! This lint is **warn** by default
 
-use crate::utils::{is_automatically_derived, snippet_opt, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::is_automatically_derived;
+use clippy_utils::source::snippet_opt;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BindingAnnotation, BorrowKind, Expr, ExprKind, Item, Mutability, Pat, PatKind};
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 f449f397e7d..7fbffe04a3f 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs
@@ -1,4 +1,5 @@
-use crate::utils::{snippet_with_applicability, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet_with_applicability;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BindingAnnotation, Mutability, Node, Pat, PatKind};
diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs
index 30fe2d6225c..91c97ef7c2a 100644
--- a/src/tools/clippy/clippy_lints/src/needless_continue.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs
@@ -33,14 +33,14 @@
 //! ```
 //!
 //! This lint is **warn** by default.
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::source::{indent_of, snippet, snippet_block};
 use rustc_ast::ast;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::{original_sp, DUMMY_SP};
 use rustc_span::Span;
 
-use crate::utils::{indent_of, snippet, snippet_block, span_lint_and_help};
-
 declare_clippy_lint! {
     /// **What it does:** The lint checks for `if`-statements appearing in loops
     /// that contain a `continue` statement in either their main blocks or their
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 d439577f9c3..e70c248e87b 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
@@ -1,8 +1,8 @@
-use crate::utils::ptr::get_spans;
-use crate::utils::{
-    get_trait_def_id, implements_trait, is_copy, is_self, is_type_diagnostic_item, multispan_sugg, paths, snippet,
-    snippet_opt, span_lint_and_then,
-};
+use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
+use clippy_utils::ptr::get_spans;
+use clippy_utils::source::{snippet, snippet_opt};
+use clippy_utils::ty::{implements_trait, is_copy, is_type_diagnostic_item};
+use clippy_utils::{get_trait_def_id, is_self, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::Attribute;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -335,5 +335,5 @@ impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt {
 
     fn mutate(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {}
 
-    fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) { }
+    fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) {}
 }
diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
index a3293f1b361..9852633b734 100644
--- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
@@ -1,3 +1,8 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{differing_macro_contexts, is_ok_ctor, is_some_ctor, meets_msrv};
+use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Body, Expr, ExprKind, LangItem, MatchSource, QPath};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -5,9 +10,6 @@ use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::sym;
 
-use crate::utils;
-use if_chain::if_chain;
-
 declare_clippy_lint! {
     /// **What it does:**
     /// Suggests alternatives for useless applications of `?` in terminating expressions
@@ -138,13 +140,13 @@ fn emit_lint(cx: &LateContext<'_>, expr: &SomeOkCall<'_>) {
         SomeOkCall::OkCall(outer, inner) | SomeOkCall::SomeCall(outer, inner) => (outer, inner),
     };
 
-    utils::span_lint_and_sugg(
+    span_lint_and_sugg(
         cx,
         NEEDLESS_QUESTION_MARK,
         entire_expr.span,
         "question mark operator is useless here",
         "try",
-        format!("{}", utils::snippet(cx, inner_expr.span, r#""...""#)),
+        format!("{}", snippet(cx, inner_expr.span, r#""...""#)),
         Applicability::MachineApplicable,
     );
 }
@@ -158,7 +160,7 @@ fn is_some_or_ok_call<'a>(
         // Check outer expression matches CALL_IDENT(ARGUMENT) format
         if let ExprKind::Call(path, args) = &expr.kind;
         if let ExprKind::Path(QPath::Resolved(None, path)) = &path.kind;
-        if utils::is_some_ctor(cx, path.res) || utils::is_ok_ctor(cx, path.res);
+        if is_some_ctor(cx, path.res) || is_ok_ctor(cx, path.res);
 
         // Extract inner expression from ARGUMENT
         if let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar) = &args[0].kind;
@@ -171,29 +173,34 @@ fn is_some_or_ok_call<'a>(
             // question mark operator
             let inner_expr = &args[0];
 
+            // if the inner expr is inside macro but the outer one is not, do not lint (#6921)
+            if  differing_macro_contexts(expr.span, inner_expr.span) {
+                return None;
+            }
+
             let inner_ty = cx.typeck_results().expr_ty(inner_expr);
             let outer_ty = cx.typeck_results().expr_ty(expr);
 
             // Check if outer and inner type are Option
-            let outer_is_some = utils::is_type_diagnostic_item(cx, outer_ty, sym::option_type);
-            let inner_is_some = utils::is_type_diagnostic_item(cx, inner_ty, sym::option_type);
+            let outer_is_some = is_type_diagnostic_item(cx, outer_ty, sym::option_type);
+            let inner_is_some = is_type_diagnostic_item(cx, inner_ty, sym::option_type);
 
             // Check for Option MSRV
-            let meets_option_msrv = utils::meets_msrv(nqml.msrv.as_ref(), &NEEDLESS_QUESTION_MARK_OPTION_MSRV);
+            let meets_option_msrv = meets_msrv(nqml.msrv.as_ref(), &NEEDLESS_QUESTION_MARK_OPTION_MSRV);
             if outer_is_some && inner_is_some && meets_option_msrv {
                 return Some(SomeOkCall::SomeCall(expr, inner_expr));
             }
 
             // Check if outer and inner type are Result
-            let outer_is_result = utils::is_type_diagnostic_item(cx, outer_ty, sym::result_type);
-            let inner_is_result = utils::is_type_diagnostic_item(cx, inner_ty, sym::result_type);
+            let outer_is_result = is_type_diagnostic_item(cx, outer_ty, sym::result_type);
+            let inner_is_result = is_type_diagnostic_item(cx, inner_ty, sym::result_type);
 
             // Additional check: if the error type of the Result can be converted
             // via the From trait, then don't match
             let does_not_call_from = !has_implicit_error_from(cx, expr, inner_expr);
 
             // Must meet Result MSRV
-            let meets_result_msrv = utils::meets_msrv(nqml.msrv.as_ref(), &NEEDLESS_QUESTION_MARK_RESULT_MSRV);
+            let meets_result_msrv = meets_msrv(nqml.msrv.as_ref(), &NEEDLESS_QUESTION_MARK_RESULT_MSRV);
             if outer_is_result && inner_is_result && does_not_call_from && meets_result_msrv {
                 return Some(SomeOkCall::OkCall(expr, inner_expr));
             }
diff --git a/src/tools/clippy/clippy_lints/src/needless_update.rs b/src/tools/clippy/clippy_lints/src/needless_update.rs
index 41cf541ecf5..e93de8a252a 100644
--- a/src/tools/clippy/clippy_lints/src/needless_update.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_update.rs
@@ -1,4 +1,4 @@
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
diff --git a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
index ec0ad58ca9c..4b935c7b906 100644
--- a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
@@ -1,11 +1,12 @@
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::ty::implements_trait;
+use clippy_utils::{self, get_trait_def_id, paths};
 use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use crate::utils::{self, paths, span_lint};
-
 declare_clippy_lint! {
     /// **What it does:**
     /// Checks for the usage of negated comparison operators on types which only implement
@@ -59,8 +60,8 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd {
                 let ty = cx.typeck_results().expr_ty(left);
 
                 let implements_ord = {
-                    if let Some(id) = utils::get_trait_def_id(cx, &paths::ORD) {
-                        utils::implements_trait(cx, ty, id, &[])
+                    if let Some(id) = get_trait_def_id(cx, &paths::ORD) {
+                        implements_trait(cx, ty, id, &[])
                     } else {
                         return;
                     }
@@ -68,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd {
 
                 let implements_partial_ord = {
                     if let Some(id) = cx.tcx.lang_items().partial_ord_trait() {
-                        utils::implements_trait(cx, ty, id, &[])
+                        implements_trait(cx, ty, id, &[])
                     } else {
                         return;
                     }
diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
index ef7cc65cfcf..7b00879251f 100644
--- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs
+++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
@@ -1,3 +1,4 @@
+use clippy_utils::diagnostics::span_lint;
 use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
@@ -5,7 +6,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 
 use crate::consts::{self, Constant};
-use crate::utils::span_lint;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for multiplication by -1 as a form of negation.
diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs
index de2899c3462..3789572ad43 100644
--- a/src/tools/clippy/clippy_lints/src/new_without_default.rs
+++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs
@@ -1,6 +1,8 @@
-use crate::utils::paths;
-use crate::utils::sugg::DiagnosticBuilderExt;
-use crate::utils::{get_trait_def_id, return_ty, span_lint_hir_and_then};
+use clippy_utils::diagnostics::span_lint_hir_and_then;
+use clippy_utils::paths;
+use clippy_utils::source::snippet;
+use clippy_utils::sugg::DiagnosticBuilderExt;
+use clippy_utils::{get_trait_def_id, return_ty};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -61,7 +63,10 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
     #[allow(clippy::too_many_lines)]
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
         if let hir::ItemKind::Impl(hir::Impl {
-            of_trait: None, items, ..
+            of_trait: None,
+            ref generics,
+            items,
+            ..
         }) = item.kind
         {
             for assoc_item in items {
@@ -125,6 +130,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
                                         }
                                     }
 
+                                    let generics_sugg = snippet(cx, generics.span, "");
                                     span_lint_hir_and_then(
                                         cx,
                                         NEW_WITHOUT_DEFAULT,
@@ -139,7 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
                                                 cx,
                                                 item.span,
                                                 "try this",
-                                                &create_new_without_default_suggest_msg(self_ty),
+                                                &create_new_without_default_suggest_msg(self_ty, &generics_sugg),
                                                 Applicability::MaybeIncorrect,
                                             );
                                         },
@@ -154,12 +160,12 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
     }
 }
 
-fn create_new_without_default_suggest_msg(ty: Ty<'_>) -> String {
+fn create_new_without_default_suggest_msg(ty: Ty<'_>, generics_sugg: &str) -> String {
     #[rustfmt::skip]
     format!(
-"impl Default for {} {{
+"impl{} Default for {} {{
     fn default() -> Self {{
         Self::new()
     }}
-}}", ty)
+}}", generics_sugg, ty)
 }
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index 69302d695ce..83953a16bc8 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -1,4 +1,6 @@
-use crate::utils::{has_drop, snippet_opt, span_lint, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::has_drop;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource};
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 3e1db233696..aa1d8fbe300 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -4,6 +4,9 @@
 
 use std::ptr;
 
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::in_constant;
+use if_chain::if_chain;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{
@@ -18,9 +21,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{InnerSpan, Span, DUMMY_SP};
 use rustc_typeck::hir_ty_to_ty;
 
-use crate::utils::{in_constant, span_lint_and_then};
-use if_chain::if_chain;
-
 // FIXME: this is a correctness problem but there's no suitable
 // warn-by-default category.
 declare_clippy_lint! {
@@ -179,17 +179,15 @@ fn is_value_unfrozen_poly<'tcx>(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<
 fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
     let substs = cx.typeck_results().node_substs(hir_id);
 
-    let result = cx
-        .tcx
-        .const_eval_resolve(
-            cx.param_env,
-            ty::Unevaluated {
-                def: ty::WithOptConstParam::unknown(def_id),
-                substs,
-                promoted: None
-            },
-            None
-        );
+    let result = cx.tcx.const_eval_resolve(
+        cx.param_env,
+        ty::Unevaluated {
+            def: ty::WithOptConstParam::unknown(def_id),
+            substs,
+            promoted: None,
+        },
+        None,
+    );
     is_value_unfrozen_raw(cx, result, ty)
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
index d5222a030d7..4c8bceaf2cb 100644
--- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
+++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
@@ -1,4 +1,4 @@
-use crate::utils::{span_lint, span_lint_and_then};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use rustc_ast::ast::{
     Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, FnKind, Item, ItemKind, Local, Pat,
     PatKind,
diff --git a/src/tools/clippy/clippy_lints/src/open_options.rs b/src/tools/clippy/clippy_lints/src/open_options.rs
index 07ca196990d..c61dff4b8e0 100644
--- a/src/tools/clippy/clippy_lints/src/open_options.rs
+++ b/src/tools/clippy/clippy_lints/src/open_options.rs
@@ -1,4 +1,6 @@
-use crate::utils::{match_type, paths, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::paths;
+use clippy_utils::ty::match_type;
 use rustc_ast::ast::LitKind;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
index fd653044a1b..a0bc324e026 100644
--- a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
@@ -1,4 +1,5 @@
-use crate::utils::{is_direct_expn_of, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::is_direct_expn_of;
 use if_chain::if_chain;
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_lint::{EarlyContext, EarlyLintPass};
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 9ef0d267b0b..a76a4a33f1f 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
@@ -1,9 +1,10 @@
-use crate::utils;
-use crate::utils::eager_or_lazy;
-use crate::utils::sugg::Sugg;
-use crate::utils::{is_type_diagnostic_item, paths, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::paths;
+use clippy_utils::sugg::Sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::usage::contains_return_break_continue_macro;
+use clippy_utils::{eager_or_lazy, get_enclosing_block, in_macro, match_qpath};
 use if_chain::if_chain;
-
 use rustc_errors::Applicability;
 use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, MatchSource, Mutability, PatKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
@@ -108,7 +109,7 @@ fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> {
 /// If this is the else body of an if/else expression, then we need to wrap
 /// it in curly braces. Otherwise, we don't.
 fn should_wrap_in_braces(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| {
+    get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| {
         let mut should_wrap = false;
 
         if let Some(Expr {
@@ -158,15 +159,15 @@ fn detect_option_if_let_else<'tcx>(
     expr: &'_ Expr<'tcx>,
 ) -> Option<OptionIfLetElseOccurence> {
     if_chain! {
-        if !utils::in_macro(expr.span); // Don't lint macros, because it behaves weirdly
+        if !in_macro(expr.span); // Don't lint macros, because it behaves weirdly
         if let ExprKind::Match(cond_expr, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind;
         if arms.len() == 2;
         if !is_result_ok(cx, cond_expr); // Don't lint on Result::ok because a different lint does it already
         if let PatKind::TupleStruct(struct_qpath, &[inner_pat], _) = &arms[0].pat.kind;
-        if utils::match_qpath(struct_qpath, &paths::OPTION_SOME);
+        if match_qpath(struct_qpath, &paths::OPTION_SOME);
         if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind;
-        if !utils::usage::contains_return_break_continue_macro(arms[0].body);
-        if !utils::usage::contains_return_break_continue_macro(arms[1].body);
+        if !contains_return_break_continue_macro(arms[0].body);
+        if !contains_return_break_continue_macro(arms[1].body);
         then {
             let capture_mut = if bind_annotation == &BindingAnnotation::Mutable { "mut " } else { "" };
             let some_body = extract_body_from_arm(&arms[0])?;
diff --git a/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs b/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs
index 3c041bac234..cf667c6e805 100644
--- a/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs
+++ b/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs
@@ -1,4 +1,5 @@
-use crate::utils::{span_lint, SpanlessEq};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::SpanlessEq;
 use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs
index 207423a1861..d32b937b209 100644
--- a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs
@@ -1,4 +1,6 @@
-use crate::utils::{find_macro_calls, is_type_diagnostic_item, return_ty, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{find_macro_calls, return_ty};
 use rustc_hir as hir;
 use rustc_hir::intravisit::FnKind;
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
index 359620cc079..d06e7f8fe1e 100644
--- a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
+++ b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
@@ -1,4 +1,5 @@
-use crate::utils::{is_expn_of, match_panic_call, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{is_expn_of, match_panic_call};
 use if_chain::if_chain;
 use rustc_hir::Expr;
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs
index aca1ed5ca65..1251ddd9a02 100644
--- a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs
@@ -1,4 +1,5 @@
-use crate::utils::{is_automatically_derived, span_lint_hir};
+use clippy_utils::diagnostics::span_lint_hir;
+use clippy_utils::is_automatically_derived;
 use if_chain::if_chain;
 use rustc_hir::{Impl, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index ff700aa5146..e151f85a391 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -1,6 +1,10 @@
 use std::cmp;
+use std::iter;
 
-use crate::utils::{is_copy, is_self_ty, snippet, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_self_ty;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_copy;
 use if_chain::if_chain;
 use rustc_ast::attr;
 use rustc_errors::Applicability;
@@ -119,7 +123,7 @@ impl<'tcx> PassByRefOrValue {
 
         let fn_body = cx.enclosing_body.map(|id| cx.tcx.hir().body(id));
 
-        for (index, (input, &ty)) in decl.inputs.iter().zip(fn_sig.inputs()).enumerate() {
+        for (index, (input, &ty)) in iter::zip(decl.inputs, fn_sig.inputs()).enumerate() {
             // All spans generated from a proc-macro invocation are the same...
             match span {
                 Some(s) if s == input.span => return,
diff --git a/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs b/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs
index 4a7b0ad07aa..95ffae28d8c 100644
--- a/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs
+++ b/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs
@@ -1,4 +1,5 @@
-use crate::utils::{is_type_diagnostic_item, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
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 e76c8624b6f..c0c2ab67e38 100644
--- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
@@ -1,6 +1,7 @@
-use crate::utils::{last_path_segment, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::last_path_segment;
 use rustc_hir::{
-    intravisit, Body, Expr, ExprKind, PatField, FnDecl, HirId, LocalSource, MatchSource, Mutability, Pat, PatKind,
+    intravisit, Body, Expr, ExprKind, FnDecl, HirId, LocalSource, MatchSource, Mutability, Pat, PatField, PatKind,
     QPath, Stmt, StmtKind,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -9,6 +10,7 @@ use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{AdtDef, FieldDef, Ty, TyKind, VariantDef};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
+use std::iter;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for patterns that aren't exact representations of the types
@@ -133,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch {
         hir_id: HirId,
     ) {
         if let Some(fn_sig) = cx.typeck_results().liberated_fn_sigs().get(hir_id) {
-            for (param, ty) in body.params.iter().zip(fn_sig.inputs().iter()) {
+            for (param, ty) in iter::zip(body.params, fn_sig.inputs()) {
                 apply_lint(cx, &param.pat, ty, DerefPossible::Impossible);
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/precedence.rs b/src/tools/clippy/clippy_lints/src/precedence.rs
index c9d18c3cb72..9cf00c953b9 100644
--- a/src/tools/clippy/clippy_lints/src/precedence.rs
+++ b/src/tools/clippy/clippy_lints/src/precedence.rs
@@ -1,4 +1,5 @@
-use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
 use if_chain::if_chain;
 use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind, UnOp};
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 6ea2d8b06d8..be686b1b0cd 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -1,10 +1,10 @@
 //! Checks for usage of  `&Vec[_]` and `&String`.
 
-use crate::utils::ptr::get_spans;
-use crate::utils::{
-    is_allowed, is_type_diagnostic_item, match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_sugg,
-    span_lint_and_then, walk_ptrs_hir_ty,
-};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::ptr::get_spans;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::{is_type_diagnostic_item, match_type, walk_ptrs_hir_ty};
+use clippy_utils::{is_allowed, match_qpath, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{
diff --git a/src/tools/clippy/clippy_lints/src/ptr_eq.rs b/src/tools/clippy/clippy_lints/src/ptr_eq.rs
index 3be792ce5e4..5796c59c8b3 100644
--- a/src/tools/clippy/clippy_lints/src/ptr_eq.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr_eq.rs
@@ -1,4 +1,6 @@
-use crate::utils;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::in_macro;
+use clippy_utils::source::snippet_opt;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
@@ -40,7 +42,7 @@ static LINT_MSG: &str = "use `std::ptr::eq` when comparing raw pointers";
 
 impl LateLintPass<'_> for PtrEq {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if utils::in_macro(expr.span) {
+        if in_macro(expr.span) {
             return;
         }
 
@@ -54,10 +56,10 @@ impl LateLintPass<'_> for PtrEq {
                 if_chain! {
                     if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left);
                     if let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right);
-                    if let Some(left_snip) = utils::snippet_opt(cx, left_var.span);
-                    if let Some(right_snip) = utils::snippet_opt(cx, right_var.span);
+                    if let Some(left_snip) = snippet_opt(cx, left_var.span);
+                    if let Some(right_snip) = snippet_opt(cx, right_var.span);
                     then {
-                        utils::span_lint_and_sugg(
+                        span_lint_and_sugg(
                             cx,
                             PTR_EQ,
                             expr.span,
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 e0996804a59..c04b4255256 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
@@ -1,4 +1,5 @@
-use crate::utils::{snippet_opt, span_lint, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::source::snippet_opt;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index 6c480d48c75..2054255a7c9 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -1,3 +1,8 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::sugg::Sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{eq_expr_value, match_def_path, match_qpath, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
@@ -6,12 +11,6 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
 
-use crate::utils::sugg::Sugg;
-use crate::utils::{
-    eq_expr_value, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet_with_applicability,
-    span_lint_and_sugg,
-};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for expressions that could be replaced by the question mark operator.
     ///
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index 59503817c0f..95b21489eb5 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -1,4 +1,9 @@
 use crate::consts::{constant, Constant};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
+use clippy_utils::sugg::Sugg;
+use clippy_utils::{get_parent_expr, in_constant, is_integer_const, meets_msrv, single_segment_path};
+use clippy_utils::{higher, SpanlessEq};
 use if_chain::if_chain;
 use rustc_ast::ast::RangeLimits;
 use rustc_errors::Applicability;
@@ -12,13 +17,6 @@ use rustc_span::sym;
 use rustc_span::symbol::Ident;
 use std::cmp::Ordering;
 
-use crate::utils::sugg::Sugg;
-use crate::utils::{
-    get_parent_expr, in_constant, is_integer_const, meets_msrv, single_segment_path, snippet, snippet_opt,
-    snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then,
-};
-use crate::utils::{higher, SpanlessEq};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for zipping a collection with the range of
     /// `0.._.len()`.
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index f90d4820563..3abe619207e 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -1,7 +1,7 @@
-use crate::utils::{
-    fn_has_unsatisfiable_preds, has_drop, is_copy, is_type_diagnostic_item, match_def_path, paths, snippet_opt,
-    span_lint_hir, span_lint_hir_and_then, walk_ptrs_ty_depth,
-};
+use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, walk_ptrs_ty_depth};
+use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths};
 use if_chain::if_chain;
 use rustc_data_structures::{fx::FxHashMap, transitive_relation::TransitiveRelation};
 use rustc_errors::Applicability;
@@ -556,7 +556,7 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> {
                     mir::Operand::Copy(p) | mir::Operand::Move(p) => {
                         self.possible_borrower.add(p.local, *dest);
                     },
-                    _ => (),
+                    mir::Operand::Constant(..) => (),
                 }
             }
         }
@@ -578,7 +578,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
 
     let mut visit_op = |op: &mir::Operand<'_>| match op {
         mir::Operand::Copy(p) | mir::Operand::Move(p) => visit(p.local),
-        _ => (),
+        mir::Operand::Constant(..) => (),
     };
 
     match rvalue {
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 f398b3fff25..2977a108d14 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -1,4 +1,5 @@
-use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_then};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
+use clippy_utils::source::snippet_with_applicability;
 use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_ast::visit as ast_visit;
diff --git a/src/tools/clippy/clippy_lints/src/redundant_else.rs b/src/tools/clippy/clippy_lints/src/redundant_else.rs
index 3d585cd27a3..061526c6f09 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_else.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_else.rs
@@ -1,4 +1,4 @@
-use crate::utils::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{Block, Expr, ExprKind, Stmt, StmtKind};
 use rustc_ast::visit::{walk_expr, Visitor};
 use rustc_lint::{EarlyContext, EarlyLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
index 9688ef39331..abebd422797 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
@@ -1,4 +1,5 @@
-use crate::utils::{meets_msrv, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::meets_msrv;
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
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 c876bae2303..e091095de13 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
@@ -1,4 +1,4 @@
-use crate::utils::span_lint_and_then;
+use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind, VisibilityKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
index e5ced13514f..6da7b5fbcc8 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
@@ -1,3 +1,6 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::is_type_lang_item;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem};
@@ -5,8 +8,6 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::{lint::in_external_macro, ty::TyS};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use crate::utils::{is_type_lang_item, snippet_with_applicability, span_lint_and_sugg};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for redundant slicing expressions which use the full range, and
     /// do not change the type.
diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
index fcfa3c12755..32b57698ec5 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
@@ -1,4 +1,6 @@
-use crate::utils::{meets_msrv, snippet, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::meets_msrv;
+use clippy_utils::source::snippet;
 use rustc_ast::ast::{Item, ItemKind, Ty, TyKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs
index 8cd6692ce03..0922cfa494e 100644
--- a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs
@@ -1,12 +1,13 @@
-use crate::utils::{last_path_segment, snippet, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::last_path_segment;
+use clippy_utils::source::snippet;
+use if_chain::if_chain;
+use rustc_errors::Applicability;
 use rustc_hir::{GenericArg, Mutability, Ty, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::sym;
 
-use if_chain::if_chain;
-use rustc_errors::Applicability;
-
 declare_clippy_lint! {
     /// **What it does:** Checks for usage of `&Option<&T>`.
     ///
diff --git a/src/tools/clippy/clippy_lints/src/reference.rs b/src/tools/clippy/clippy_lints/src/reference.rs
index e1450466a7c..d6336389b0a 100644
--- a/src/tools/clippy/clippy_lints/src/reference.rs
+++ b/src/tools/clippy/clippy_lints/src/reference.rs
@@ -1,5 +1,7 @@
-use crate::utils::sugg::Sugg;
-use crate::utils::{in_macro, snippet_opt, snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::in_macro;
+use clippy_utils::source::{snippet_opt, snippet_with_applicability};
+use clippy_utils::sugg::Sugg;
 use if_chain::if_chain;
 use rustc_ast::ast::{Expr, ExprKind, Mutability, UnOp};
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs
index 1edea613148..1cc332de894 100644
--- a/src/tools/clippy/clippy_lints/src/regex.rs
+++ b/src/tools/clippy/clippy_lints/src/regex.rs
@@ -1,5 +1,6 @@
 use crate::consts::{constant, Constant};
-use crate::utils::{match_def_path, paths, span_lint, span_lint_and_help};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::{LitKind, StrStyle};
 use rustc_data_structures::fx::FxHashSet;
diff --git a/src/tools/clippy/clippy_lints/src/repeat_once.rs b/src/tools/clippy/clippy_lints/src/repeat_once.rs
index d34e744eb94..63e5ec69e66 100644
--- a/src/tools/clippy/clippy_lints/src/repeat_once.rs
+++ b/src/tools/clippy/clippy_lints/src/repeat_once.rs
@@ -1,5 +1,8 @@
 use crate::consts::{constant_context, Constant};
-use crate::utils::{in_macro, is_type_diagnostic_item, snippet, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::in_macro;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_type_diagnostic_item;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 40c0f1f4589..8995ae431ad 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -1,3 +1,6 @@
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::source::snippet_opt;
+use clippy_utils::{fn_def_id, in_macro, match_qpath};
 use if_chain::if_chain;
 use rustc_ast::ast::Attribute;
 use rustc_errors::Applicability;
@@ -11,8 +14,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 use rustc_span::sym;
 
-use crate::utils::{fn_def_id, in_macro, match_qpath, snippet_opt, span_lint_and_sugg, span_lint_and_then};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for `let`-bindings, which are subsequently
     /// returned.
diff --git a/src/tools/clippy/clippy_lints/src/self_assignment.rs b/src/tools/clippy/clippy_lints/src/self_assignment.rs
index e096c9aebc1..e7925c4fbde 100644
--- a/src/tools/clippy/clippy_lints/src/self_assignment.rs
+++ b/src/tools/clippy/clippy_lints/src/self_assignment.rs
@@ -1,4 +1,6 @@
-use crate::utils::{eq_expr_value, snippet, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::eq_expr_value;
+use clippy_utils::source::snippet;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
index 839c995e525..f61af15fbed 100644
--- a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
+++ b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
@@ -1,4 +1,6 @@
-use crate::utils::{in_macro, snippet_with_macro_callsite, span_lint_and_sugg, sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_macro_callsite;
+use clippy_utils::{in_macro, sugg};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Block, ExprKind};
diff --git a/src/tools/clippy/clippy_lints/src/serde_api.rs b/src/tools/clippy/clippy_lints/src/serde_api.rs
index 90cf1b6c861..169f7d26285 100644
--- a/src/tools/clippy/clippy_lints/src/serde_api.rs
+++ b/src/tools/clippy/clippy_lints/src/serde_api.rs
@@ -1,4 +1,5 @@
-use crate::utils::{get_trait_def_id, paths, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{get_trait_def_id, paths};
 use rustc_hir::{Impl, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs
index 32f6bc74642..612d2fd84cb 100644
--- a/src/tools/clippy/clippy_lints/src/shadow.rs
+++ b/src/tools/clippy/clippy_lints/src/shadow.rs
@@ -1,4 +1,6 @@
-use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet;
+use clippy_utils::{contains_name, higher, iter_input_pats};
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
     Block, Body, Expr, ExprKind, FnDecl, Guard, HirId, Local, MutTy, Pat, PatKind, Path, QPath, StmtKind, Ty, TyKind,
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 1fc4ff5c2e6..c9d72aabb6a 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,4 +1,5 @@
-use crate::utils::{in_macro, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::in_macro;
 use if_chain::if_chain;
 use rustc_ast::{Item, ItemKind, UseTreeKind};
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs
index 87e386baadc..09e00866815 100644
--- a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs
+++ b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs
@@ -1,7 +1,8 @@
 //! Lint on use of `size_of` or `size_of_val` of T in an expression
 //! expecting a count of T
 
-use crate::utils::{match_def_path, paths, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_hir::BinOpKind;
 use rustc_hir::{Expr, ExprKind};
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 96f6881556c..d55a83f1613 100644
--- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
@@ -1,5 +1,6 @@
-use crate::utils::sugg::Sugg;
-use crate::utils::{get_enclosing_block, match_qpath, span_lint_and_then, SpanlessEq};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sugg::Sugg;
+use clippy_utils::{get_enclosing_block, match_qpath, SpanlessEq};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/stable_sort_primitive.rs b/src/tools/clippy/clippy_lints/src/stable_sort_primitive.rs
index 276a9338819..65790375c73 100644
--- a/src/tools/clippy/clippy_lints/src/stable_sort_primitive.rs
+++ b/src/tools/clippy/clippy_lints/src/stable_sort_primitive.rs
@@ -1,7 +1,6 @@
-use crate::utils::{is_slice_of_primitives, span_lint_and_then, sugg::Sugg};
-
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::{is_slice_of_primitives, sugg::Sugg};
 use if_chain::if_chain;
-
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index 31dd5965473..99ca7ef77a5 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -1,3 +1,9 @@
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::source::{snippet, snippet_with_applicability};
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::SpanlessEq;
+use clippy_utils::{get_parent_expr, is_allowed, match_function_call, method_calls, paths};
+use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, QPath};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -7,14 +13,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Spanned;
 use rustc_span::sym;
 
-use if_chain::if_chain;
-
-use crate::utils::SpanlessEq;
-use crate::utils::{
-    get_parent_expr, is_allowed, is_type_diagnostic_item, match_function_call, method_calls, paths, span_lint,
-    span_lint_and_help, span_lint_and_sugg,
-};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for string appends of the form `x = x + y` (without
     /// `let`!).
@@ -205,7 +203,6 @@ declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES, STRING_FROM_UTF8_AS
 
 impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        use crate::utils::{snippet, snippet_with_applicability};
         use rustc_ast::LitKind;
 
         if_chain! {
@@ -287,6 +284,35 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
                 }
             }
         }
+
+        if_chain! {
+            if let ExprKind::MethodCall(path, _, [recv], _) = &e.kind;
+            if path.ident.name == sym!(into_bytes);
+            if let ExprKind::MethodCall(path, _, [recv], _) = &recv.kind;
+            if matches!(&*path.ident.name.as_str(), "to_owned" | "to_string");
+            if let ExprKind::Lit(lit) = &recv.kind;
+            if let LitKind::Str(lit_content, _) = &lit.node;
+
+            if lit_content.as_str().is_ascii();
+            if lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT;
+            if !recv.span.from_expansion();
+            then {
+                let mut applicability = Applicability::MachineApplicable;
+
+                span_lint_and_sugg(
+                    cx,
+                    STRING_LIT_AS_BYTES,
+                    e.span,
+                    "calling `into_bytes()` on a string literal",
+                    "consider using a byte string literal instead",
+                    format!(
+                        "b{}.to_vec()",
+                        snippet_with_applicability(cx, recv.span, r#""..""#, &mut applicability)
+                    ),
+                    applicability,
+                );
+            }
+        }
     }
 }
 
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 9acc47deb06..46f423204a2 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
@@ -1,5 +1,6 @@
-use crate::utils::ast_utils::{eq_id, is_useless_with_eq_exprs, IdentIter};
-use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::ast_utils::{eq_id, is_useless_with_eq_exprs, IdentIter};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
 use core::ops::{Add, AddAssign};
 use if_chain::if_chain;
 use rustc_ast::ast::{BinOpKind, Expr, ExprKind, StmtKind};
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
index 0b7d08cb164..99e3d818b79 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
@@ -1,4 +1,5 @@
-use crate::utils::{get_trait_def_id, span_lint, trait_ref_of_method};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{get_trait_def_id, paths, trait_ref_of_method};
 use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
@@ -158,7 +159,7 @@ fn check_binop(
     expected_ops: &[hir::BinOpKind],
 ) -> Option<&'static str> {
     let mut trait_ids = vec![];
-    let [krate, module] = crate::utils::paths::OPS_MODULE;
+    let [krate, module] = paths::OPS_MODULE;
 
     for &t in traits {
         let path = [krate, module, t];
diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs
index 9d8a0c24833..14519eaa962 100644
--- a/src/tools/clippy/clippy_lints/src/swap.rs
+++ b/src/tools/clippy/clippy_lints/src/swap.rs
@@ -1,7 +1,8 @@
-use crate::utils::sugg::Sugg;
-use crate::utils::{
-    differing_macro_contexts, eq_expr_value, is_type_diagnostic_item, snippet_with_applicability, span_lint_and_then,
-};
+use clippy_utils::diagnostics::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::{differing_macro_contexts, eq_expr_value};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, StmtKind};
diff --git a/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs b/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs
index 74ccd9235de..88bd2feaadd 100644
--- a/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs
+++ b/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs
@@ -1,4 +1,4 @@
-use crate::utils::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_sugg;
 use rustc_ast::ast;
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/temporary_assignment.rs b/src/tools/clippy/clippy_lints/src/temporary_assignment.rs
index fb891866364..8ef25dc816c 100644
--- a/src/tools/clippy/clippy_lints/src/temporary_assignment.rs
+++ b/src/tools/clippy/clippy_lints/src/temporary_assignment.rs
@@ -1,4 +1,5 @@
-use crate::utils::{is_adjusted, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::is_adjusted;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
index eeda39bfa20..c66a596c784 100644
--- a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
+++ b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
@@ -1,4 +1,6 @@
-use crate::utils::{match_def_path, snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::match_def_path;
+use clippy_utils::source::snippet_with_applicability;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
diff --git a/src/tools/clippy/clippy_lints/src/to_string_in_display.rs b/src/tools/clippy/clippy_lints/src/to_string_in_display.rs
index 84ec2aa18ab..42ec14c31b5 100644
--- a/src/tools/clippy/clippy_lints/src/to_string_in_display.rs
+++ b/src/tools/clippy/clippy_lints/src/to_string_in_display.rs
@@ -1,4 +1,5 @@
-use crate::utils::{is_diagnostic_assoc_item, match_def_path, path_to_local_id, paths, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{is_diagnostic_assoc_item, match_def_path, path_to_local_id, paths};
 use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index daff5f81e8c..3ff27c3bcf4 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -1,4 +1,6 @@
-use crate::utils::{in_macro, snippet, snippet_with_applicability, span_lint_and_help, SpanlessHash};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::source::{snippet, snippet_with_applicability};
+use clippy_utils::{in_macro, SpanlessHash};
 use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs
index ce87defaa94..25d0543c861 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs
@@ -1,5 +1,5 @@
 use super::CROSSPOINTER_TRANSMUTE;
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
index c1870f5208b..47d58bd30db 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
@@ -12,7 +12,7 @@ mod useless_transmute;
 mod utils;
 mod wrong_transmute;
 
-use crate::utils::{in_constant, match_def_path, paths};
+use clippy_utils::{in_constant, match_def_path, paths};
 use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
index 562d880e39a..72489f27cd3 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
@@ -1,5 +1,6 @@
 use super::TRANSMUTE_FLOAT_TO_INT;
-use crate::utils::{span_lint_and_then, sugg};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sugg;
 use if_chain::if_chain;
 use rustc_ast as ast;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs
index 5b609f906a3..cc0a5643e2a 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs
@@ -1,5 +1,6 @@
 use super::TRANSMUTE_INT_TO_BOOL;
-use crate::utils::{span_lint_and_then, sugg};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sugg;
 use rustc_ast as ast;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs
index 29d2450618a..8f884e6a4a1 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs
@@ -1,5 +1,6 @@
 use super::TRANSMUTE_INT_TO_CHAR;
-use crate::utils::{span_lint_and_then, sugg};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sugg;
 use rustc_ast as ast;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
index f83fba8966a..2b6a4cff81e 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
@@ -1,5 +1,6 @@
 use super::TRANSMUTE_INT_TO_FLOAT;
-use crate::utils::{span_lint_and_then, sugg};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sugg;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
index f4e60a3020c..7b646bfc0c6 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
@@ -1,5 +1,6 @@
 use super::TRANSMUTE_PTR_TO_PTR;
-use crate::utils::{span_lint_and_then, sugg};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sugg;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
index f5dbbbe33bc..f14eef93645 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
@@ -1,6 +1,7 @@
 use super::utils::get_type_snippet;
 use super::TRANSMUTE_PTR_TO_REF;
-use crate::utils::{span_lint_and_then, sugg};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sugg;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Mutability, QPath};
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
index 01b00bb0a22..d105e37abf9 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
@@ -1,5 +1,7 @@
 use super::{TRANSMUTE_BYTES_TO_STR, TRANSMUTE_PTR_TO_PTR};
-use crate::utils::{snippet, span_lint_and_sugg, span_lint_and_then, sugg};
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::source::snippet;
+use clippy_utils::sugg;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Mutability};
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
index dea896622f1..e2c6d130f3c 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
@@ -1,6 +1,7 @@
 use super::utils::can_be_expressed_as_pointer_cast;
 use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
-use crate::utils::{span_lint_and_then, sugg};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sugg;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs
index 503c5e0ff38..de9277e016e 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs
@@ -1,6 +1,7 @@
 use super::utils::is_layout_incompatible;
 use super::UNSOUND_COLLECTION_TRANSMUTE;
-use crate::utils::{match_def_path, paths, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{match_def_path, paths};
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
diff --git a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
index 83441514af0..445bcf60fa7 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
@@ -1,5 +1,6 @@
 use super::USELESS_TRANSMUTE;
-use crate::utils::{span_lint, span_lint_and_then, sugg};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
+use clippy_utils::sugg;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
index 55008d8ec3f..c6d0d63b0b5 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
@@ -1,4 +1,6 @@
-use crate::utils::{is_normalizable, last_path_segment, snippet};
+use clippy_utils::last_path_segment;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_normalizable;
 use if_chain::if_chain;
 use rustc_hir::{Expr, GenericArg, QPath, TyKind};
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs
index d6d77f2c834..2118f3d6950 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs
@@ -1,5 +1,5 @@
 use super::WRONG_TRANSMUTE;
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
diff --git a/src/tools/clippy/clippy_lints/src/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmuting_null.rs
index 2ba2b646f00..d42cdde110e 100644
--- a/src/tools/clippy/clippy_lints/src/transmuting_null.rs
+++ b/src/tools/clippy/clippy_lints/src/transmuting_null.rs
@@ -1,5 +1,6 @@
 use crate::consts::{constant_context, Constant};
-use crate::utils::{match_qpath, paths, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{match_qpath, paths};
 use if_chain::if_chain;
 use rustc_ast::LitKind;
 use rustc_hir::{Expr, ExprKind};
diff --git a/src/tools/clippy/clippy_lints/src/try_err.rs b/src/tools/clippy/clippy_lints/src/try_err.rs
index 73e3a04aec9..e61058c2749 100644
--- a/src/tools/clippy/clippy_lints/src/try_err.rs
+++ b/src/tools/clippy/clippy_lints/src/try_err.rs
@@ -1,7 +1,7 @@
-use crate::utils::{
-    differing_macro_contexts, in_macro, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet,
-    snippet_with_macro_callsite, span_lint_and_sugg,
-};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::{snippet, snippet_with_macro_callsite};
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{differing_macro_contexts, in_macro, match_def_path, match_qpath, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath};
diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
index 81090040d92..d68c6db4e23 100644
--- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
@@ -1,3 +1,7 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::{match_path, paths};
+use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{
     self as hir, GenericArg, GenericBounds, GenericParamKind, HirId, Lifetime, MutTy, Mutability, Node, QPath,
@@ -5,10 +9,6 @@ use rustc_hir::{
 };
 use rustc_lint::LateContext;
 
-use if_chain::if_chain;
-
-use crate::utils::{match_path, paths, snippet, span_lint_and_sugg};
-
 use super::BORROWED_BOX;
 
 pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, mut_ty: &MutTy<'_>) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/types/box_vec.rs b/src/tools/clippy/clippy_lints/src/types/box_vec.rs
index 6aa98e435e1..d8b1953457c 100644
--- a/src/tools/clippy/clippy_lints/src/types/box_vec.rs
+++ b/src/tools/clippy/clippy_lints/src/types/box_vec.rs
@@ -1,9 +1,9 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::is_ty_param_diagnostic_item;
 use rustc_hir::{self as hir, def_id::DefId, QPath};
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
 
-use crate::utils::{is_ty_param_diagnostic_item, span_lint_and_help};
-
 use super::BOX_VEC;
 
 pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/types/linked_list.rs b/src/tools/clippy/clippy_lints/src/types/linked_list.rs
index 47eb4ede4e4..a9fbe7aa315 100644
--- a/src/tools/clippy/clippy_lints/src/types/linked_list.rs
+++ b/src/tools/clippy/clippy_lints/src/types/linked_list.rs
@@ -1,8 +1,8 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::{match_def_path, paths};
 use rustc_hir::{self as hir, def_id::DefId};
 use rustc_lint::LateContext;
 
-use crate::utils::{match_def_path, paths, span_lint_and_help};
-
 use super::LINKEDLIST;
 
 pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, def_id: DefId) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index 4a1a608e8ae..c73c1c9d92d 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -13,21 +13,22 @@ use std::borrow::Cow;
 use std::cmp::Ordering;
 use std::collections::BTreeMap;
 
+use clippy_utils::diagnostics::{multispan_sugg, span_lint, span_lint_and_help, span_lint_and_then};
+use clippy_utils::source::{snippet, snippet_opt};
+use clippy_utils::ty::{is_isize_or_usize, is_type_diagnostic_item};
 use if_chain::if_chain;
-use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_errors::DiagnosticBuilder;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
 use rustc_hir::{
-    BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericParamKind, HirId, ImplItem,
-    ImplItemKind, Item, ItemKind, Local, MatchSource, MutTy, Node, QPath, Stmt, StmtKind, TraitFn, TraitItem,
-    TraitItemKind, TyKind,
+    BinOpKind, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericParamKind, HirId, ImplItem,
+    ImplItemKind, Item, ItemKind, Local, MutTy, QPath, TraitFn, TraitItem, TraitItemKind, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::map::Map;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, IntTy, Ty, TyS, TypeckResults, UintTy};
 use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
-use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::sym;
 use rustc_target::abi::LayoutOf;
@@ -35,12 +36,8 @@ use rustc_target::spec::abi::Abi;
 use rustc_typeck::hir_ty_to_ty;
 
 use crate::consts::{constant, Constant};
-use crate::utils::paths;
-use crate::utils::{
-    clip, comparisons, differing_macro_contexts, higher, indent_of, int_bits, is_isize_or_usize,
-    is_type_diagnostic_item, match_path, multispan_sugg, reindent_multiline, sext, snippet, snippet_opt,
-    snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_then, unsext,
-};
+use clippy_utils::paths;
+use clippy_utils::{clip, comparisons, differing_macro_contexts, int_bits, match_path, sext, unsext};
 
 declare_clippy_lint! {
     /// **What it does:** Checks for use of `Box<Vec<_>>` anywhere in the code.
@@ -279,7 +276,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
         match item.kind {
             TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_ty(cx, ty, false),
             TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, &sig.decl),
-            _ => (),
+            TraitItemKind::Type(..) => (),
         }
     }
 
@@ -391,390 +388,6 @@ impl Types {
 }
 
 declare_clippy_lint! {
-    /// **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.
-    ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
-    /// ```rust
-    /// let x = {
-    ///     1;
-    /// };
-    /// ```
-    pub LET_UNIT_VALUE,
-    pedantic,
-    "creating a `let` binding to a value of unit type, which usually can't be used afterwards"
-}
-
-declare_lint_pass!(LetUnitValue => [LET_UNIT_VALUE]);
-
-impl<'tcx> LateLintPass<'tcx> for LetUnitValue {
-    fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
-        if let StmtKind::Local(ref local) = stmt.kind {
-            if is_unit(cx.typeck_results().pat_ty(&local.pat)) {
-                if in_external_macro(cx.sess(), stmt.span) || local.pat.span.from_expansion() {
-                    return;
-                }
-                if higher::is_from_for_desugar(local) {
-                    return;
-                }
-                span_lint_and_then(
-                    cx,
-                    LET_UNIT_VALUE,
-                    stmt.span,
-                    "this let-binding has unit value",
-                    |diag| {
-                        if let Some(expr) = &local.init {
-                            let snip = snippet_with_macro_callsite(cx, expr.span, "()");
-                            diag.span_suggestion(
-                                stmt.span,
-                                "omit the `let` binding",
-                                format!("{};", snip),
-                                Applicability::MachineApplicable, // snippet
-                            );
-                        }
-                    },
-                );
-            }
-        }
-    }
-}
-
-declare_clippy_lint! {
-    /// **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.
-    ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
-    /// ```rust
-    /// # fn foo() {};
-    /// # fn bar() {};
-    /// # fn baz() {};
-    /// if {
-    ///     foo();
-    /// } == {
-    ///     bar();
-    /// } {
-    ///     baz();
-    /// }
-    /// ```
-    /// is equal to
-    /// ```rust
-    /// # fn foo() {};
-    /// # fn bar() {};
-    /// # fn baz() {};
-    /// {
-    ///     foo();
-    ///     bar();
-    ///     baz();
-    /// }
-    /// ```
-    ///
-    /// For asserts:
-    /// ```rust
-    /// # fn foo() {};
-    /// # fn bar() {};
-    /// assert_eq!({ foo(); }, { bar(); });
-    /// ```
-    /// will always succeed
-    pub UNIT_CMP,
-    correctness,
-    "comparing unit values"
-}
-
-declare_lint_pass!(UnitCmp => [UNIT_CMP]);
-
-impl<'tcx> LateLintPass<'tcx> for UnitCmp {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if expr.span.from_expansion() {
-            if let Some(callee) = expr.span.source_callee() {
-                if let ExpnKind::Macro(MacroKind::Bang, symbol) = callee.kind {
-                    if let ExprKind::Binary(ref cmp, ref left, _) = expr.kind {
-                        let op = cmp.node;
-                        if op.is_comparison() && is_unit(cx.typeck_results().expr_ty(left)) {
-                            let result = match &*symbol.as_str() {
-                                "assert_eq" | "debug_assert_eq" => "succeed",
-                                "assert_ne" | "debug_assert_ne" => "fail",
-                                _ => return,
-                            };
-                            span_lint(
-                                cx,
-                                UNIT_CMP,
-                                expr.span,
-                                &format!(
-                                    "`{}` of unit values detected. This will always {}",
-                                    symbol.as_str(),
-                                    result
-                                ),
-                            );
-                        }
-                    }
-                }
-            }
-            return;
-        }
-        if let ExprKind::Binary(ref cmp, ref left, _) = expr.kind {
-            let op = cmp.node;
-            if op.is_comparison() && is_unit(cx.typeck_results().expr_ty(left)) {
-                let result = match op {
-                    BinOpKind::Eq | BinOpKind::Le | BinOpKind::Ge => "true",
-                    _ => "false",
-                };
-                span_lint(
-                    cx,
-                    UNIT_CMP,
-                    expr.span,
-                    &format!(
-                        "{}-comparison of unit values detected. This will always be {}",
-                        op.as_str(),
-                        result
-                    ),
-                );
-            }
-        }
-    }
-}
-
-declare_clippy_lint! {
-    /// **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.
-    ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
-    /// ```rust,ignore
-    /// foo({
-    ///     let a = bar();
-    ///     baz(a);
-    /// })
-    /// ```
-    pub UNIT_ARG,
-    complexity,
-    "passing unit to a function"
-}
-
-declare_lint_pass!(UnitArg => [UNIT_ARG]);
-
-impl<'tcx> LateLintPass<'tcx> for UnitArg {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if expr.span.from_expansion() {
-            return;
-        }
-
-        // apparently stuff in the desugaring of `?` can trigger this
-        // so check for that here
-        // only the calls to `Try::from_error` is marked as desugared,
-        // so we need to check both the current Expr and its parent.
-        if is_questionmark_desugar_marked_call(expr) {
-            return;
-        }
-        if_chain! {
-            let map = &cx.tcx.hir();
-            let opt_parent_node = map.find(map.get_parent_node(expr.hir_id));
-            if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node;
-            if is_questionmark_desugar_marked_call(parent_expr);
-            then {
-                return;
-            }
-        }
-
-        match expr.kind {
-            ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => {
-                let args_to_recover = args
-                    .iter()
-                    .filter(|arg| {
-                        if is_unit(cx.typeck_results().expr_ty(arg)) && !is_unit_literal(arg) {
-                            !matches!(
-                                &arg.kind,
-                                ExprKind::Match(.., MatchSource::TryDesugar) | ExprKind::Path(..)
-                            )
-                        } else {
-                            false
-                        }
-                    })
-                    .collect::<Vec<_>>();
-                if !args_to_recover.is_empty() {
-                    lint_unit_args(cx, expr, &args_to_recover);
-                }
-            },
-            _ => (),
-        }
-    }
-}
-
-fn fmt_stmts_and_call(
-    cx: &LateContext<'_>,
-    call_expr: &Expr<'_>,
-    call_snippet: &str,
-    args_snippets: &[impl AsRef<str>],
-    non_empty_block_args_snippets: &[impl AsRef<str>],
-) -> String {
-    let call_expr_indent = indent_of(cx, call_expr.span).unwrap_or(0);
-    let call_snippet_with_replacements = args_snippets
-        .iter()
-        .fold(call_snippet.to_owned(), |acc, arg| acc.replacen(arg.as_ref(), "()", 1));
-
-    let mut stmts_and_call = non_empty_block_args_snippets
-        .iter()
-        .map(|it| it.as_ref().to_owned())
-        .collect::<Vec<_>>();
-    stmts_and_call.push(call_snippet_with_replacements);
-    stmts_and_call = stmts_and_call
-        .into_iter()
-        .map(|v| reindent_multiline(v.into(), true, Some(call_expr_indent)).into_owned())
-        .collect();
-
-    let mut stmts_and_call_snippet = stmts_and_call.join(&format!("{}{}", ";\n", " ".repeat(call_expr_indent)));
-    // expr is not in a block statement or result expression position, wrap in a block
-    let parent_node = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(call_expr.hir_id));
-    if !matches!(parent_node, Some(Node::Block(_))) && !matches!(parent_node, Some(Node::Stmt(_))) {
-        let block_indent = call_expr_indent + 4;
-        stmts_and_call_snippet =
-            reindent_multiline(stmts_and_call_snippet.into(), true, Some(block_indent)).into_owned();
-        stmts_and_call_snippet = format!(
-            "{{\n{}{}\n{}}}",
-            " ".repeat(block_indent),
-            &stmts_and_call_snippet,
-            " ".repeat(call_expr_indent)
-        );
-    }
-    stmts_and_call_snippet
-}
-
-fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Expr<'_>]) {
-    let mut applicability = Applicability::MachineApplicable;
-    let (singular, plural) = if args_to_recover.len() > 1 {
-        ("", "s")
-    } else {
-        ("a ", "")
-    };
-    span_lint_and_then(
-        cx,
-        UNIT_ARG,
-        expr.span,
-        &format!("passing {}unit value{} to a function", singular, plural),
-        |db| {
-            let mut or = "";
-            args_to_recover
-                .iter()
-                .filter_map(|arg| {
-                    if_chain! {
-                        if let ExprKind::Block(block, _) = arg.kind;
-                        if block.expr.is_none();
-                        if let Some(last_stmt) = block.stmts.iter().last();
-                        if let StmtKind::Semi(last_expr) = last_stmt.kind;
-                        if let Some(snip) = snippet_opt(cx, last_expr.span);
-                        then {
-                            Some((
-                                last_stmt.span,
-                                snip,
-                            ))
-                        }
-                        else {
-                            None
-                        }
-                    }
-                })
-                .for_each(|(span, sugg)| {
-                    db.span_suggestion(
-                        span,
-                        "remove the semicolon from the last statement in the block",
-                        sugg,
-                        Applicability::MaybeIncorrect,
-                    );
-                    or = "or ";
-                    applicability = Applicability::MaybeIncorrect;
-                });
-
-            let arg_snippets: Vec<String> = args_to_recover
-                .iter()
-                .filter_map(|arg| snippet_opt(cx, arg.span))
-                .collect();
-            let arg_snippets_without_empty_blocks: Vec<String> = args_to_recover
-                .iter()
-                .filter(|arg| !is_empty_block(arg))
-                .filter_map(|arg| snippet_opt(cx, arg.span))
-                .collect();
-
-            if let Some(call_snippet) = snippet_opt(cx, expr.span) {
-                let sugg = fmt_stmts_and_call(
-                    cx,
-                    expr,
-                    &call_snippet,
-                    &arg_snippets,
-                    &arg_snippets_without_empty_blocks,
-                );
-
-                if arg_snippets_without_empty_blocks.is_empty() {
-                    db.multipart_suggestion(
-                        &format!("use {}unit literal{} instead", singular, plural),
-                        args_to_recover
-                            .iter()
-                            .map(|arg| (arg.span, "()".to_string()))
-                            .collect::<Vec<_>>(),
-                        applicability,
-                    );
-                } else {
-                    let plural = arg_snippets_without_empty_blocks.len() > 1;
-                    let empty_or_s = if plural { "s" } else { "" };
-                    let it_or_them = if plural { "them" } else { "it" };
-                    db.span_suggestion(
-                        expr.span,
-                        &format!(
-                            "{}move the expression{} in front of the call and replace {} with the unit literal `()`",
-                            or, empty_or_s, it_or_them
-                        ),
-                        sugg,
-                        applicability,
-                    );
-                }
-            }
-        },
-    );
-}
-
-fn is_empty_block(expr: &Expr<'_>) -> bool {
-    matches!(
-        expr.kind,
-        ExprKind::Block(
-            Block {
-                stmts: &[],
-                expr: None,
-                ..
-            },
-            _,
-        )
-    )
-}
-
-fn is_questionmark_desugar_marked_call(expr: &Expr<'_>) -> bool {
-    use rustc_span::hygiene::DesugaringKind;
-    if let ExprKind::Call(ref callee, _) = expr.kind {
-        callee.span.is_desugaring(DesugaringKind::QuestionMark)
-    } else {
-        false
-    }
-}
-
-fn is_unit(ty: Ty<'_>) -> bool {
-    matches!(ty.kind(), ty::Tuple(slice) if slice.is_empty())
-}
-
-fn is_unit_literal(expr: &Expr<'_>) -> bool {
-    matches!(expr.kind, ExprKind::Tup(ref slice) if slice.is_empty())
-}
-
-declare_clippy_lint! {
     /// **What it does:** Checks for types used in structs, parameters and `let`
     /// declarations above a certain complexity threshold.
     ///
@@ -839,7 +452,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeComplexity {
             TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty),
             TraitItemKind::Fn(FnSig { ref decl, .. }, TraitFn::Required(_)) => self.check_fndecl(cx, decl),
             // methods with default impl are covered by check_fn
-            _ => (),
+            TraitItemKind::Type(..) | TraitItemKind::Fn(_, TraitFn::Provided(_)) => (),
         }
     }
 
@@ -847,7 +460,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeComplexity {
         match item.kind {
             ImplItemKind::Const(ref ty, _) | ImplItemKind::TyAlias(ref ty) => self.check_type(cx, ty),
             // methods are covered by check_fn
-            _ => (),
+            ImplItemKind::Fn(..) => (),
         }
     }
 
@@ -911,7 +524,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
             // function types bring a lot of overhead
             TyKind::BareFn(ref bare) if bare.abi == Abi::Rust => (50 * self.nest, 1),
 
-            TyKind::TraitObject(ref param_bounds, ..) => {
+            TyKind::TraitObject(ref param_bounds, _, _) => {
                 let has_lifetime_parameters = param_bounds.iter().any(|bound| {
                     bound
                         .bound_generic_params
@@ -1005,7 +618,7 @@ fn detect_absurd_comparison<'tcx>(
 ) -> Option<(ExtremeExpr<'tcx>, AbsurdComparisonResult)> {
     use crate::types::AbsurdComparisonResult::{AlwaysFalse, AlwaysTrue, InequalityImpossible};
     use crate::types::ExtremeType::{Maximum, Minimum};
-    use crate::utils::comparisons::{normalize_comparison, Rel};
+    use clippy_utils::comparisons::{normalize_comparison, Rel};
 
     // absurd comparison only makes sense on primitive types
     // primitive types don't implement comparison operators with each other
@@ -1247,7 +860,7 @@ fn upcast_comparison_bounds_err<'tcx>(
     rhs: &'tcx Expr<'_>,
     invert: bool,
 ) {
-    use crate::utils::comparisons::Rel;
+    use clippy_utils::comparisons::Rel;
 
     if let Some((lb, ub)) = lhs_bounds {
         if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) {
diff --git a/src/tools/clippy/clippy_lints/src/types/option_option.rs b/src/tools/clippy/clippy_lints/src/types/option_option.rs
index dc5db963b4e..b2692c48076 100644
--- a/src/tools/clippy/clippy_lints/src/types/option_option.rs
+++ b/src/tools/clippy/clippy_lints/src/types/option_option.rs
@@ -1,9 +1,9 @@
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::is_ty_param_diagnostic_item;
 use rustc_hir::{self as hir, def_id::DefId, QPath};
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
 
-use crate::utils::{is_ty_param_diagnostic_item, span_lint};
-
 use super::OPTION_OPTION;
 
 pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs b/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs
index e34b95147e1..ef629a35d10 100644
--- a/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs
+++ b/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs
@@ -1,12 +1,11 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::{get_qpath_generic_tys, is_ty_param_diagnostic_item};
 use rustc_errors::Applicability;
 use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind};
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
 
-use crate::utils::{
-    get_qpath_generic_tys, is_ty_param_diagnostic_item, snippet_with_applicability, span_lint_and_sugg,
-};
-
 use super::RC_BUFFER;
 
 pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
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 5da6db179c4..c0c1f340583 100644
--- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
+++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
@@ -1,13 +1,11 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::{get_qpath_generic_tys, is_ty_param_diagnostic_item, is_ty_param_lang_item};
 use rustc_errors::Applicability;
 use rustc_hir::{self as hir, def_id::DefId, LangItem, QPath, TyKind};
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
 
-use crate::utils::{
-    get_qpath_generic_tys, is_ty_param_diagnostic_item, is_ty_param_lang_item, snippet_with_applicability,
-    span_lint_and_sugg,
-};
-
 use super::{utils, REDUNDANT_ALLOCATION};
 
 pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/types/utils.rs b/src/tools/clippy/clippy_lints/src/types/utils.rs
index 4d64748f998..45f891ed718 100644
--- a/src/tools/clippy/clippy_lints/src/types/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/types/utils.rs
@@ -1,11 +1,9 @@
+use clippy_utils::last_path_segment;
+use if_chain::if_chain;
 use rustc_hir::{GenericArg, QPath, TyKind};
 use rustc_lint::LateContext;
 use rustc_span::source_map::Span;
 
-use crate::utils::last_path_segment;
-
-use if_chain::if_chain;
-
 pub(super) fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<Span> {
     let last = last_path_segment(qpath);
     if_chain! {
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 2530cc133c6..d2c373db261 100644
--- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
@@ -1,3 +1,7 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::last_path_segment;
+use clippy_utils::source::snippet;
+use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{self as hir, def_id::DefId, GenericArg, QPath, TyKind};
 use rustc_lint::LateContext;
@@ -6,10 +10,6 @@ use rustc_span::symbol::sym;
 use rustc_target::abi::LayoutOf;
 use rustc_typeck::hir_ty_to_ty;
 
-use if_chain::if_chain;
-
-use crate::utils::{last_path_segment, snippet, span_lint_and_sugg};
-
 use super::VEC_BOX;
 
 pub(super) fn check(
diff --git a/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs b/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs
index 5443f1601fc..b6749069176 100644
--- a/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs
+++ b/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs
@@ -1,4 +1,6 @@
-use crate::utils::{is_type_lang_item, match_function_call, paths, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::ty::is_type_lang_item;
+use clippy_utils::{match_function_call, paths};
 use rustc_hir::{lang_items, Expr};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/unicode.rs b/src/tools/clippy/clippy_lints/src/unicode.rs
index 93d59cc7fcd..d81e31f5a21 100644
--- a/src/tools/clippy/clippy_lints/src/unicode.rs
+++ b/src/tools/clippy/clippy_lints/src/unicode.rs
@@ -1,4 +1,6 @@
-use crate::utils::{is_allowed, snippet, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_allowed;
+use clippy_utils::source::snippet;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, HirId};
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
index c6ae8b9b598..4c13941f665 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -1,4 +1,5 @@
-use crate::utils::{get_trait_def_id, paths, span_lint, span_lint_and_help};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::{get_trait_def_id, paths};
 use if_chain::if_chain;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, ExprKind, StmtKind};
@@ -43,7 +44,7 @@ fn get_trait_predicates_for_trait_id<'tcx>(
     for (pred, _) in generics.predicates {
         if_chain! {
             if let PredicateKind::Trait(poly_trait_pred, _) = pred.kind().skip_binder();
-            let trait_pred = cx.tcx.erase_late_bound_regions(ty::Binder::bind(poly_trait_pred));
+            let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred));
             if let Some(trait_def_id) = trait_id;
             if trait_def_id == trait_pred.trait_ref.def_id;
             then {
@@ -57,12 +58,12 @@ fn get_trait_predicates_for_trait_id<'tcx>(
 fn get_projection_pred<'tcx>(
     cx: &LateContext<'tcx>,
     generics: GenericPredicates<'tcx>,
-    pred: TraitPredicate<'tcx>,
+    trait_pred: TraitPredicate<'tcx>,
 ) -> Option<ProjectionPredicate<'tcx>> {
     generics.predicates.iter().find_map(|(proj_pred, _)| {
-        if let ty::PredicateKind::Projection(proj_pred) = proj_pred.kind().skip_binder() {
-            let projection_pred = cx.tcx.erase_late_bound_regions(ty::Binder::bind(proj_pred));
-            if projection_pred.projection_ty.substs == pred.trait_ref.substs {
+        if let ty::PredicateKind::Projection(pred) = proj_pred.kind().skip_binder() {
+            let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred.kind().rebind(pred));
+            if projection_pred.projection_ty.substs == trait_pred.trait_ref.substs {
                 return Some(projection_pred);
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
new file mode 100644
index 00000000000..8698a718bbd
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
@@ -0,0 +1,39 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::higher;
+use clippy_utils::source::snippet_with_macro_callsite;
+use rustc_errors::Applicability;
+use rustc_hir::{Stmt, StmtKind};
+use rustc_lint::{LateContext, LintContext};
+use rustc_middle::lint::in_external_macro;
+
+use super::LET_UNIT_VALUE;
+
+pub(super) fn check(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
+    if let StmtKind::Local(ref local) = stmt.kind {
+        if cx.typeck_results().pat_ty(&local.pat).is_unit() {
+            if in_external_macro(cx.sess(), stmt.span) || local.pat.span.from_expansion() {
+                return;
+            }
+            if higher::is_from_for_desugar(local) {
+                return;
+            }
+            span_lint_and_then(
+                cx,
+                LET_UNIT_VALUE,
+                stmt.span,
+                "this let-binding has unit value",
+                |diag| {
+                    if let Some(expr) = &local.init {
+                        let snip = snippet_with_macro_callsite(cx, expr.span, "()");
+                        diag.span_suggestion(
+                            stmt.span,
+                            "omit the `let` binding",
+                            format!("{};", snip),
+                            Applicability::MachineApplicable, // snippet
+                        );
+                    }
+                },
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/mod.rs b/src/tools/clippy/clippy_lints/src/unit_types/mod.rs
new file mode 100644
index 00000000000..64420a03933
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/unit_types/mod.rs
@@ -0,0 +1,107 @@
+mod let_unit_value;
+mod unit_arg;
+mod unit_cmp;
+mod utils;
+
+use rustc_hir::{Expr, Stmt};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// **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.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust
+    /// let x = {
+    ///     1;
+    /// };
+    /// ```
+    pub LET_UNIT_VALUE,
+    pedantic,
+    "creating a `let` binding to a value of unit type, which usually can't be used afterwards"
+}
+
+declare_clippy_lint! {
+    /// **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.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust
+    /// # fn foo() {};
+    /// # fn bar() {};
+    /// # fn baz() {};
+    /// if {
+    ///     foo();
+    /// } == {
+    ///     bar();
+    /// } {
+    ///     baz();
+    /// }
+    /// ```
+    /// is equal to
+    /// ```rust
+    /// # fn foo() {};
+    /// # fn bar() {};
+    /// # fn baz() {};
+    /// {
+    ///     foo();
+    ///     bar();
+    ///     baz();
+    /// }
+    /// ```
+    ///
+    /// For asserts:
+    /// ```rust
+    /// # fn foo() {};
+    /// # fn bar() {};
+    /// assert_eq!({ foo(); }, { bar(); });
+    /// ```
+    /// will always succeed
+    pub UNIT_CMP,
+    correctness,
+    "comparing unit values"
+}
+
+declare_clippy_lint! {
+    /// **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.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust,ignore
+    /// foo({
+    ///     let a = bar();
+    ///     baz(a);
+    /// })
+    /// ```
+    pub UNIT_ARG,
+    complexity,
+    "passing unit to a function"
+}
+
+declare_lint_pass!(UnitTypes => [LET_UNIT_VALUE, UNIT_CMP, UNIT_ARG]);
+
+impl LateLintPass<'_> for UnitTypes {
+    fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) {
+        let_unit_value::check(cx, stmt);
+    }
+
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        unit_cmp::check(cx, expr);
+        unit_arg::check(cx, expr);
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
new file mode 100644
index 00000000000..925ab577099
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
@@ -0,0 +1,207 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
+use if_chain::if_chain;
+use rustc_errors::Applicability;
+use rustc_hir::{self as hir, Block, Expr, ExprKind, MatchSource, Node, StmtKind};
+use rustc_lint::LateContext;
+
+use super::{utils, UNIT_ARG};
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
+    if expr.span.from_expansion() {
+        return;
+    }
+
+    // apparently stuff in the desugaring of `?` can trigger this
+    // so check for that here
+    // only the calls to `Try::from_error` is marked as desugared,
+    // so we need to check both the current Expr and its parent.
+    if is_questionmark_desugar_marked_call(expr) {
+        return;
+    }
+    if_chain! {
+        let map = &cx.tcx.hir();
+        let opt_parent_node = map.find(map.get_parent_node(expr.hir_id));
+        if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node;
+        if is_questionmark_desugar_marked_call(parent_expr);
+        then {
+            return;
+        }
+    }
+
+    match expr.kind {
+        ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => {
+            let args_to_recover = args
+                .iter()
+                .filter(|arg| {
+                    if cx.typeck_results().expr_ty(arg).is_unit() && !utils::is_unit_literal(arg) {
+                        !matches!(
+                            &arg.kind,
+                            ExprKind::Match(.., MatchSource::TryDesugar) | ExprKind::Path(..)
+                        )
+                    } else {
+                        false
+                    }
+                })
+                .collect::<Vec<_>>();
+            if !args_to_recover.is_empty() {
+                lint_unit_args(cx, expr, &args_to_recover);
+            }
+        },
+        _ => (),
+    }
+}
+
+fn is_questionmark_desugar_marked_call(expr: &Expr<'_>) -> bool {
+    use rustc_span::hygiene::DesugaringKind;
+    if let ExprKind::Call(ref callee, _) = expr.kind {
+        callee.span.is_desugaring(DesugaringKind::QuestionMark)
+    } else {
+        false
+    }
+}
+
+fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Expr<'_>]) {
+    let mut applicability = Applicability::MachineApplicable;
+    let (singular, plural) = if args_to_recover.len() > 1 {
+        ("", "s")
+    } else {
+        ("a ", "")
+    };
+    span_lint_and_then(
+        cx,
+        UNIT_ARG,
+        expr.span,
+        &format!("passing {}unit value{} to a function", singular, plural),
+        |db| {
+            let mut or = "";
+            args_to_recover
+                .iter()
+                .filter_map(|arg| {
+                    if_chain! {
+                        if let ExprKind::Block(block, _) = arg.kind;
+                        if block.expr.is_none();
+                        if let Some(last_stmt) = block.stmts.iter().last();
+                        if let StmtKind::Semi(last_expr) = last_stmt.kind;
+                        if let Some(snip) = snippet_opt(cx, last_expr.span);
+                        then {
+                            Some((
+                                last_stmt.span,
+                                snip,
+                            ))
+                        }
+                        else {
+                            None
+                        }
+                    }
+                })
+                .for_each(|(span, sugg)| {
+                    db.span_suggestion(
+                        span,
+                        "remove the semicolon from the last statement in the block",
+                        sugg,
+                        Applicability::MaybeIncorrect,
+                    );
+                    or = "or ";
+                    applicability = Applicability::MaybeIncorrect;
+                });
+
+            let arg_snippets: Vec<String> = args_to_recover
+                .iter()
+                .filter_map(|arg| snippet_opt(cx, arg.span))
+                .collect();
+            let arg_snippets_without_empty_blocks: Vec<String> = args_to_recover
+                .iter()
+                .filter(|arg| !is_empty_block(arg))
+                .filter_map(|arg| snippet_opt(cx, arg.span))
+                .collect();
+
+            if let Some(call_snippet) = snippet_opt(cx, expr.span) {
+                let sugg = fmt_stmts_and_call(
+                    cx,
+                    expr,
+                    &call_snippet,
+                    &arg_snippets,
+                    &arg_snippets_without_empty_blocks,
+                );
+
+                if arg_snippets_without_empty_blocks.is_empty() {
+                    db.multipart_suggestion(
+                        &format!("use {}unit literal{} instead", singular, plural),
+                        args_to_recover
+                            .iter()
+                            .map(|arg| (arg.span, "()".to_string()))
+                            .collect::<Vec<_>>(),
+                        applicability,
+                    );
+                } else {
+                    let plural = arg_snippets_without_empty_blocks.len() > 1;
+                    let empty_or_s = if plural { "s" } else { "" };
+                    let it_or_them = if plural { "them" } else { "it" };
+                    db.span_suggestion(
+                        expr.span,
+                        &format!(
+                            "{}move the expression{} in front of the call and replace {} with the unit literal `()`",
+                            or, empty_or_s, it_or_them
+                        ),
+                        sugg,
+                        applicability,
+                    );
+                }
+            }
+        },
+    );
+}
+
+fn is_empty_block(expr: &Expr<'_>) -> bool {
+    matches!(
+        expr.kind,
+        ExprKind::Block(
+            Block {
+                stmts: &[],
+                expr: None,
+                ..
+            },
+            _,
+        )
+    )
+}
+
+fn fmt_stmts_and_call(
+    cx: &LateContext<'_>,
+    call_expr: &Expr<'_>,
+    call_snippet: &str,
+    args_snippets: &[impl AsRef<str>],
+    non_empty_block_args_snippets: &[impl AsRef<str>],
+) -> String {
+    let call_expr_indent = indent_of(cx, call_expr.span).unwrap_or(0);
+    let call_snippet_with_replacements = args_snippets
+        .iter()
+        .fold(call_snippet.to_owned(), |acc, arg| acc.replacen(arg.as_ref(), "()", 1));
+
+    let mut stmts_and_call = non_empty_block_args_snippets
+        .iter()
+        .map(|it| it.as_ref().to_owned())
+        .collect::<Vec<_>>();
+    stmts_and_call.push(call_snippet_with_replacements);
+    stmts_and_call = stmts_and_call
+        .into_iter()
+        .map(|v| reindent_multiline(v.into(), true, Some(call_expr_indent)).into_owned())
+        .collect();
+
+    let mut stmts_and_call_snippet = stmts_and_call.join(&format!("{}{}", ";\n", " ".repeat(call_expr_indent)));
+    // expr is not in a block statement or result expression position, wrap in a block
+    let parent_node = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(call_expr.hir_id));
+    if !matches!(parent_node, Some(Node::Block(_))) && !matches!(parent_node, Some(Node::Stmt(_))) {
+        let block_indent = call_expr_indent + 4;
+        stmts_and_call_snippet =
+            reindent_multiline(stmts_and_call_snippet.into(), true, Some(block_indent)).into_owned();
+        stmts_and_call_snippet = format!(
+            "{{\n{}{}\n{}}}",
+            " ".repeat(block_indent),
+            &stmts_and_call_snippet,
+            " ".repeat(call_expr_indent)
+        );
+    }
+    stmts_and_call_snippet
+}
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs
new file mode 100644
index 00000000000..b3077dec5d8
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs
@@ -0,0 +1,56 @@
+use clippy_utils::diagnostics::span_lint;
+use rustc_hir::{BinOpKind, Expr, ExprKind};
+use rustc_lint::LateContext;
+use rustc_span::hygiene::{ExpnKind, MacroKind};
+
+use super::UNIT_CMP;
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
+    if expr.span.from_expansion() {
+        if let Some(callee) = expr.span.source_callee() {
+            if let ExpnKind::Macro(MacroKind::Bang, symbol) = callee.kind {
+                if let ExprKind::Binary(ref cmp, ref left, _) = expr.kind {
+                    let op = cmp.node;
+                    if op.is_comparison() && cx.typeck_results().expr_ty(left).is_unit() {
+                        let result = match &*symbol.as_str() {
+                            "assert_eq" | "debug_assert_eq" => "succeed",
+                            "assert_ne" | "debug_assert_ne" => "fail",
+                            _ => return,
+                        };
+                        span_lint(
+                            cx,
+                            UNIT_CMP,
+                            expr.span,
+                            &format!(
+                                "`{}` of unit values detected. This will always {}",
+                                symbol.as_str(),
+                                result
+                            ),
+                        );
+                    }
+                }
+            }
+        }
+        return;
+    }
+
+    if let ExprKind::Binary(ref cmp, ref left, _) = expr.kind {
+        let op = cmp.node;
+        if op.is_comparison() && cx.typeck_results().expr_ty(left).is_unit() {
+            let result = match op {
+                BinOpKind::Eq | BinOpKind::Le | BinOpKind::Ge => "true",
+                _ => "false",
+            };
+            span_lint(
+                cx,
+                UNIT_CMP,
+                expr.span,
+                &format!(
+                    "{}-comparison of unit values detected. This will always be {}",
+                    op.as_str(),
+                    result
+                ),
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/utils.rs b/src/tools/clippy/clippy_lints/src/unit_types/utils.rs
new file mode 100644
index 00000000000..4e194a05e8d
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/unit_types/utils.rs
@@ -0,0 +1,5 @@
+use rustc_hir::{Expr, ExprKind};
+
+pub(super) fn is_unit_literal(expr: &Expr<'_>) -> bool {
+    matches!(expr.kind, ExprKind::Tup(ref slice) if slice.is_empty())
+}
diff --git a/src/tools/clippy/clippy_lints/src/unnamed_address.rs b/src/tools/clippy/clippy_lints/src/unnamed_address.rs
index 9582c162e77..d5bc3de6698 100644
--- a/src/tools/clippy/clippy_lints/src/unnamed_address.rs
+++ b/src/tools/clippy/clippy_lints/src/unnamed_address.rs
@@ -1,4 +1,5 @@
-use crate::utils::{match_def_path, paths, span_lint, span_lint_and_help};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs
index 00a707107bc..6becff9662a 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs
@@ -1,5 +1,6 @@
-use crate::utils;
-use crate::utils::sugg::Sugg;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::sugg::Sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath};
@@ -8,6 +9,7 @@ use rustc_middle::ty::{self, subst::GenericArgKind};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
 use rustc_span::symbol::Ident;
+use std::iter;
 
 declare_clippy_lint! {
     /// **What it does:**
@@ -78,17 +80,15 @@ fn mirrored_exprs(
             mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident)
         },
         // Two arrays with mirrored contents
-        (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => left_exprs
-            .iter()
-            .zip(right_exprs.iter())
-            .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)),
+        (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => {
+            iter::zip(*left_exprs, *right_exprs)
+                .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
+        }
         // The two exprs are function calls.
         // Check to see that the function itself and its arguments are mirrored
         (ExprKind::Call(left_expr, left_args), ExprKind::Call(right_expr, right_args)) => {
             mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident)
-                && left_args
-                    .iter()
-                    .zip(right_args.iter())
+                && iter::zip(*left_args, *right_args)
                     .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
         },
         // The two exprs are method calls.
@@ -99,16 +99,14 @@ fn mirrored_exprs(
             ExprKind::MethodCall(right_segment, _, right_args, _),
         ) => {
             left_segment.ident == right_segment.ident
-                && left_args
-                    .iter()
-                    .zip(right_args.iter())
+                && iter::zip(*left_args, *right_args)
                     .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
-        },
+        }
         // Two tuples with mirrored contents
-        (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => left_exprs
-            .iter()
-            .zip(right_exprs.iter())
-            .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)),
+        (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => {
+            iter::zip(*left_exprs, *right_exprs)
+                .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
+        }
         // Two binary ops, which are the same operation and which have mirrored arguments
         (ExprKind::Binary(left_op, left_left, left_right), ExprKind::Binary(right_op, right_left, right_right)) => {
             left_op.node == right_op.node
@@ -145,9 +143,7 @@ fn mirrored_exprs(
                 },
             )),
         ) => {
-            (left_segments
-                .iter()
-                .zip(right_segments.iter())
+            (iter::zip(*left_segments, *right_segments)
                 .all(|(left, right)| left.ident == right.ident)
                 && left_segments
                     .iter()
@@ -176,7 +172,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> {
         if let name = name_ident.ident.name.to_ident_string();
         if name == "sort_by" || name == "sort_unstable_by";
         if let [vec, Expr { kind: ExprKind::Closure(_, _, closure_body_id, _, _), .. }] = args;
-        if utils::is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(vec), sym::vec_type);
+        if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(vec), sym::vec_type);
         if let closure_body = cx.tcx.hir().body(*closure_body_id);
         if let &[
             Param { pat: Pat { kind: PatKind::Binding(_, _, left_ident, _), .. }, ..},
@@ -232,7 +228,7 @@ fn expr_borrows(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 impl LateLintPass<'_> for UnnecessarySortBy {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         match detect_lint(cx, expr) {
-            Some(LintTrigger::SortByKey(trigger)) => utils::span_lint_and_sugg(
+            Some(LintTrigger::SortByKey(trigger)) => span_lint_and_sugg(
                 cx,
                 UNNECESSARY_SORT_BY,
                 expr.span,
@@ -255,7 +251,7 @@ impl LateLintPass<'_> for UnnecessarySortBy {
                     Applicability::MachineApplicable
                 },
             ),
-            Some(LintTrigger::Sort(trigger)) => utils::span_lint_and_sugg(
+            Some(LintTrigger::Sort(trigger)) => span_lint_and_sugg(
                 cx,
                 UNNECESSARY_SORT_BY,
                 expr.span,
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
index 8e076397c11..c2be457e9dc 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
@@ -1,7 +1,6 @@
-use crate::utils::{
-    contains_return, in_macro, match_qpath, paths, return_ty, snippet, span_lint_and_then,
-    visitors::find_all_ret_expressions,
-};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet;
+use clippy_utils::{contains_return, in_macro, match_qpath, paths, return_ty, visitors::find_all_ret_expressions};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
@@ -72,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
                 }
             },
             FnKind::Closure => return,
-            _ => (),
+            FnKind::Method(..) => (),
         }
 
         // Abort if the method is implementing a trait or of it a trait method.
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index 5826e9a4aa5..2b9479365c6 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -1,7 +1,8 @@
 #![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
 
-use crate::utils::ast_utils::{eq_field_pat, eq_id, eq_pat, eq_path};
-use crate::utils::{over, span_lint_and_then};
+use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_pat, eq_path};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::over;
 use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, Pat, PatKind, PatKind::*, DUMMY_NODE_ID};
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 154082a0fdb..16ad9d2dfd3 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
@@ -1,4 +1,4 @@
-use crate::utils::span_lint;
+use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast::{Item, ItemKind, UseTree, UseTreeKind};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
index 43166d26787..9990052e114 100644
--- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
@@ -1,4 +1,5 @@
-use crate::utils::{is_try, match_trait_method, paths, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{is_try, match_trait_method, paths};
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs
index 812482cf5cf..aef4ce75915 100644
--- a/src/tools/clippy/clippy_lints/src/unused_self.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_self.rs
@@ -1,11 +1,10 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::visitors::LocalUsedVisitor;
 use if_chain::if_chain;
 use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use crate::utils::span_lint_and_help;
-use crate::utils::visitors::LocalUsedVisitor;
-
 declare_clippy_lint! {
     /// **What it does:** Checks methods that contain a `self` argument but don't use it
     ///
diff --git a/src/tools/clippy/clippy_lints/src/unused_unit.rs b/src/tools/clippy/clippy_lints/src/unused_unit.rs
index a31cd5fda84..329ea49024b 100644
--- a/src/tools/clippy/clippy_lints/src/unused_unit.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_unit.rs
@@ -1,3 +1,5 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::position_before_rarrow;
 use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_ast::visit::FnKind;
@@ -7,8 +9,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 use rustc_span::BytePos;
 
-use crate::utils::{position_before_rarrow, span_lint_and_sugg};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for unit (`()`) expressions that can be removed.
     ///
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index 2fb0463c5a6..fb29acca18a 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -1,6 +1,6 @@
-use crate::utils::{
-    differing_macro_contexts, is_type_diagnostic_item, span_lint_and_then, usage::is_potentially_mutated,
-};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{differing_macro_contexts, usage::is_potentially_mutated};
 use if_chain::if_chain;
 use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor};
 use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Path, QPath, UnOp};
diff --git a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
index 8cb7429849d..0d745813beb 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
@@ -1,6 +1,10 @@
-use crate::utils::{is_type_diagnostic_item, method_chain_args, return_ty, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{method_chain_args, return_ty};
 use if_chain::if_chain;
 use rustc_hir as hir;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::{Expr, ImplItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty;
@@ -66,9 +70,6 @@ impl<'tcx> LateLintPass<'tcx> for UnwrapInResult {
     }
 }
 
-use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc_hir::{Expr, ImplItemKind};
-
 struct FindExpectUnwrap<'a, 'tcx> {
     lcx: &'a LateContext<'tcx>,
     typeck_results: &'tcx ty::TypeckResults<'tcx>,
diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
index 0470e1dbbb8..a6d29d36862 100644
--- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
+++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
@@ -1,7 +1,7 @@
-use crate::utils::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_sugg;
 use if_chain::if_chain;
 use itertools::Itertools;
-use rustc_ast::ast::{Item, ItemKind, Variant};
+use rustc_ast::ast::{Item, ItemKind, Variant, VisibilityKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
@@ -81,7 +81,7 @@ fn check_ident(cx: &EarlyContext<'_>, ident: &Ident, be_aggressive: bool) {
     // assume that two-letter words are some kind of valid abbreviation like FP for false positive
     // (and don't warn)
     if (ident.chars().all(|c| c.is_ascii_uppercase()) && ident.len() > 2)
-    // otherwise, warn if we have SOmeTHING lIKE THIs but only warn with the aggressive 
+    // otherwise, warn if we have SOmeTHING lIKE THIs but only warn with the aggressive
     // upper-case-acronyms-aggressive config option enabled
     || (be_aggressive && ident != &corrected)
     {
@@ -105,6 +105,8 @@ impl EarlyLintPass for UpperCaseAcronyms {
                 it.kind,
                 ItemKind::TyAlias(..) | ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Trait(..)
             );
+            // do not lint public items
+            if !matches!(it.vis.kind, VisibilityKind::Public);
             then {
                 check_ident(cx, &it.ident, self.upper_case_acronyms_aggressive);
             }
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index f0523cec621..116cb8b1e1c 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -1,6 +1,7 @@
-use crate::utils::{in_macro, meets_msrv, snippet_opt, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::{in_macro, meets_msrv};
 use if_chain::if_chain;
-
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index c5334853986..3e1b69e676b 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -1,8 +1,8 @@
-use crate::utils::sugg::Sugg;
-use crate::utils::{
-    get_parent_expr, is_type_diagnostic_item, match_def_path, match_trait_method, paths, snippet,
-    snippet_with_macro_callsite, span_lint_and_help, span_lint_and_sugg,
-};
+use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::source::{snippet, snippet_with_macro_callsite};
+use clippy_utils::sugg::Sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{get_parent_expr, match_def_path, match_trait_method, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, HirId, MatchSource};
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index c5761480080..a92c987014f 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -1,7 +1,7 @@
 //! A group of attributes that can be attached to Rust code in order
 //! to generate a clippy lint detecting said code automatically.
 
-use crate::utils::get_attr;
+use clippy_utils::get_attr;
 use rustc_ast::ast::{LitFloatType, LitKind};
 use rustc_ast::walk_list;
 use rustc_data_structures::fx::FxHashMap;
diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
index 64ee9e65bb1..6fd3c9d7dec 100644
--- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
@@ -1,6 +1,6 @@
 //! checks for attributes
 
-use crate::utils::get_attr;
+use clippy_utils::get_attr;
 use rustc_ast::ast::{Attribute, InlineAsmTemplatePiece};
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
index 0a347516c3a..c496ff1fb24 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
@@ -1,8 +1,8 @@
 use crate::consts::{constant_simple, Constant};
-use crate::utils::{
-    is_expn_of, match_def_path, match_qpath, match_type, method_calls, path_to_res, paths, run_lints, snippet,
-    span_lint, span_lint_and_help, span_lint_and_sugg, SpanlessEq,
-};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::source::snippet;
+use clippy_utils::ty::match_type;
+use clippy_utils::{is_expn_of, match_def_path, match_qpath, method_calls, path_to_res, paths, run_lints, SpanlessEq};
 use if_chain::if_chain;
 use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, ModKind, NodeId};
 use rustc_ast::visit::FnKind;
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index be9a07f8d7c..d8b31344e6d 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -3,5 +3,3 @@ pub mod conf;
 pub mod inspector;
 #[cfg(feature = "internal-lints")]
 pub mod internal_lints;
-
-pub use clippy_utils::*;
diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs
index c132e4de4f6..1af9583887f 100644
--- a/src/tools/clippy/clippy_lints/src/vec.rs
+++ b/src/tools/clippy/clippy_lints/src/vec.rs
@@ -1,6 +1,9 @@
 use crate::consts::{constant, Constant};
 use crate::rustc_target::abi::LayoutOf;
-use crate::utils::{higher, is_copy, snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::higher;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::is_copy;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind};
diff --git a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs
index 8d111f98add..8b696ed1c84 100644
--- a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs
+++ b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs
@@ -1,6 +1,7 @@
-use crate::utils::{
-    is_type_diagnostic_item, match_def_path, path_to_local, path_to_local_id, paths, snippet, span_lint_and_sugg,
-};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{match_def_path, path_to_local, path_to_local_id, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs b/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs
index d2494b321ef..e035d3c5cad 100644
--- a/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs
@@ -1,15 +1,14 @@
-use crate::utils::span_lint_and_then;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
+use rustc_ast::LitKind;
 use rustc_errors::Applicability;
+use rustc_hir as hir;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Spanned;
 
-use crate::utils::{match_def_path, paths};
-use rustc_ast::LitKind;
-use rustc_hir as hir;
-
 declare_clippy_lint! {
     /// **What it does:** Finds occurrences of `Vec::resize(0, an_int)`
     ///
diff --git a/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs b/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs
index 32574d9d6c9..ec209b30951 100644
--- a/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs
+++ b/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs
@@ -1,4 +1,6 @@
-use crate::utils::{match_type, paths, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::paths;
+use clippy_utils::ty::match_type;
 use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs b/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs
index cd1864f461d..60c3489a449 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs
@@ -1,4 +1,5 @@
-use crate::utils::{run_lints, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::run_lints;
 use rustc_hir::{hir_id::CRATE_HIR_ID, Crate};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index 094b1a42346..51c1117d206 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -1,4 +1,6 @@
-use crate::utils::{in_macro, snippet, snippet_with_applicability, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::in_macro;
+use clippy_utils::source::{snippet, snippet_with_applicability};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index 553e6b000eb..12a47a6b703 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -1,20 +1,19 @@
 use std::borrow::Cow;
-use std::ops::Range;
-
-use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then};
-use if_chain::if_chain;
-use rustc_ast::ast::{
-    Expr, ExprKind, ImplKind, Item, ItemKind, LitKind, MacCall, StrLit, StrStyle,
-};
-use rustc_ast::token;
+use std::iter;
+use std::ops::{Deref, Range};
+
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::source::{snippet_opt, snippet_with_applicability};
+use rustc_ast::ast::{Expr, ExprKind, ImplKind, Item, ItemKind, MacCall, Path, StrLit, StrStyle};
+use rustc_ast::token::{self, LitKind};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_errors::Applicability;
 use rustc_lexer::unescape::{self, EscapeError};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_parse::parser;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::symbol::kw;
-use rustc_span::{sym, BytePos, Span};
+use rustc_span::symbol::{kw, Symbol};
+use rustc_span::{sym, BytePos, Span, DUMMY_SP};
 
 declare_clippy_lint! {
     /// **What it does:** This lint warns when you use `println!("")` to
@@ -355,7 +354,120 @@ fn newline_span(fmtstr: &StrLit) -> Span {
     sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi)
 }
 
+/// Stores a list of replacement spans for each argument, but only if all the replacements used an
+/// empty format string.
+#[derive(Default)]
+struct SimpleFormatArgs {
+    unnamed: Vec<Vec<Span>>,
+    named: Vec<(Symbol, Vec<Span>)>,
+}
+impl SimpleFormatArgs {
+    fn get_unnamed(&self) -> impl Iterator<Item = &[Span]> {
+        self.unnamed.iter().map(|x| match x.as_slice() {
+            // Ignore the dummy span added from out of order format arguments.
+            [DUMMY_SP] => &[],
+            x => x,
+        })
+    }
+
+    fn get_named(&self, n: &Path) -> &[Span] {
+        self.named.iter().find(|x| *n == x.0).map_or(&[], |x| x.1.as_slice())
+    }
+
+    fn push(&mut self, arg: rustc_parse_format::Argument<'_>, span: Span) {
+        use rustc_parse_format::{
+            AlignUnknown, ArgumentImplicitlyIs, ArgumentIs, ArgumentNamed, CountImplied, FormatSpec,
+        };
+
+        const SIMPLE: FormatSpec<'_> = FormatSpec {
+            fill: None,
+            align: AlignUnknown,
+            flags: 0,
+            precision: CountImplied,
+            precision_span: None,
+            width: CountImplied,
+            width_span: None,
+            ty: "",
+            ty_span: None,
+        };
+
+        match arg.position {
+            ArgumentIs(n) | ArgumentImplicitlyIs(n) => {
+                if self.unnamed.len() <= n {
+                    // Use a dummy span to mark all unseen arguments.
+                    self.unnamed.resize_with(n, || vec![DUMMY_SP]);
+                    if arg.format == SIMPLE {
+                        self.unnamed.push(vec![span]);
+                    } else {
+                        self.unnamed.push(Vec::new());
+                    }
+                } else {
+                    let args = &mut self.unnamed[n];
+                    match (args.as_mut_slice(), arg.format == SIMPLE) {
+                        // A non-empty format string has been seen already.
+                        ([], _) => (),
+                        // Replace the dummy span, if it exists.
+                        ([dummy @ DUMMY_SP], true) => *dummy = span,
+                        ([_, ..], true) => args.push(span),
+                        ([_, ..], false) => *args = Vec::new(),
+                    }
+                }
+            },
+            ArgumentNamed(n) => {
+                if let Some(x) = self.named.iter_mut().find(|x| x.0 == n) {
+                    match x.1.as_slice() {
+                        // A non-empty format string has been seen already.
+                        [] => (),
+                        [_, ..] if arg.format == SIMPLE => x.1.push(span),
+                        [_, ..] => x.1 = Vec::new(),
+                    }
+                } else if arg.format == SIMPLE {
+                    self.named.push((n, vec![span]));
+                } else {
+                    self.named.push((n, Vec::new()));
+                }
+            },
+        };
+    }
+}
+
 impl Write {
+    /// Parses a format string into a collection of spans for each argument. This only keeps track
+    /// of empty format arguments. Will also lint usages of debug format strings outside of debug
+    /// impls.
+    fn parse_fmt_string(&self, cx: &EarlyContext<'_>, str_lit: &StrLit) -> Option<SimpleFormatArgs> {
+        use rustc_parse_format::{ParseMode, Parser, Piece};
+
+        let str_sym = str_lit.symbol_unescaped.as_str();
+        let style = match str_lit.style {
+            StrStyle::Cooked => None,
+            StrStyle::Raw(n) => Some(n as usize),
+        };
+
+        let mut parser = Parser::new(&str_sym, style, snippet_opt(cx, str_lit.span), false, ParseMode::Format);
+        let mut args = SimpleFormatArgs::default();
+
+        while let Some(arg) = parser.next() {
+            let arg = match arg {
+                Piece::String(_) => continue,
+                Piece::NextArgument(arg) => arg,
+            };
+            let span = parser
+                .arg_places
+                .last()
+                .map_or(DUMMY_SP, |&x| str_lit.span.from_inner(x));
+
+            if !self.in_debug_impl && arg.format.ty == "?" {
+                // FIXME: modify rustc's fmt string parser to give us the current span
+                span_lint(cx, USE_DEBUG, span, "use of `Debug`-based formatting");
+            }
+
+            args.push(arg, span);
+        }
+
+        parser.errors.is_empty().then(move || args)
+    }
+
     /// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two
     /// `Option`s. The first `Option` of the tuple is the macro's format string. It includes
     /// the contents of the string, whether it's a raw string, and the span of the literal in the
@@ -376,124 +488,97 @@ impl Write {
     /// (Some("string to write: {}"), Some(buf))
     /// ```
     #[allow(clippy::too_many_lines)]
-    fn check_tts<'a>(
-        &self,
-        cx: &EarlyContext<'a>,
-        tts: TokenStream,
-        is_write: bool,
-    ) -> (Option<StrLit>, Option<Expr>) {
-        use rustc_parse_format::{
-            AlignUnknown, ArgumentImplicitlyIs, ArgumentIs, ArgumentNamed, CountImplied,
-            FormatSpec, ParseMode, Parser, Piece,
-        };
-
+    fn check_tts<'a>(&self, cx: &EarlyContext<'a>, tts: TokenStream, is_write: bool) -> (Option<StrLit>, Option<Expr>) {
         let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, false, None);
-        let mut expr: Option<Expr> = None;
-        if is_write {
-            expr = match parser.parse_expr().map_err(|mut err| err.cancel()) {
-                Ok(p) => Some(p.into_inner()),
-                Err(_) => return (None, None),
-            };
-            // might be `writeln!(foo)`
-            if parser.expect(&token::Comma).map_err(|mut err| err.cancel()).is_err() {
-                return (None, expr);
+        let expr = if is_write {
+            match parser
+                .parse_expr()
+                .map(rustc_ast::ptr::P::into_inner)
+                .map_err(|mut e| e.cancel())
+            {
+                // write!(e, ...)
+                Ok(p) if parser.eat(&token::Comma) => Some(p),
+                // write!(e) or error
+                e => return (None, e.ok()),
             }
-        }
+        } else {
+            None
+        };
 
         let fmtstr = match parser.parse_str_lit() {
             Ok(fmtstr) => fmtstr,
             Err(_) => return (None, expr),
         };
-        let tmp = fmtstr.symbol.as_str();
-        let mut args = vec![];
-        let mut fmt_parser = Parser::new(&tmp, None, None, false, ParseMode::Format);
-        while let Some(piece) = fmt_parser.next() {
-            if !fmt_parser.errors.is_empty() {
-                return (None, expr);
-            }
-            if let Piece::NextArgument(arg) = piece {
-                if !self.in_debug_impl && arg.format.ty == "?" {
-                    // FIXME: modify rustc's fmt string parser to give us the current span
-                    span_lint(
-                        cx,
-                        USE_DEBUG,
-                        parser.prev_token.span,
-                        "use of `Debug`-based formatting",
-                    );
-                }
-                args.push(arg);
-            }
-        }
+
+        let args = match self.parse_fmt_string(cx, &fmtstr) {
+            Some(args) => args,
+            None => return (Some(fmtstr), expr),
+        };
+
         let lint = if is_write { WRITE_LITERAL } else { PRINT_LITERAL };
-        let mut idx = 0;
+        let mut unnamed_args = args.get_unnamed();
         loop {
-            const SIMPLE: FormatSpec<'_> = FormatSpec {
-                fill: None,
-                align: AlignUnknown,
-                flags: 0,
-                precision: CountImplied,
-                precision_span: None,
-                width: CountImplied,
-                width_span: None,
-                ty: "",
-                ty_span: None,
-            };
             if !parser.eat(&token::Comma) {
                 return (Some(fmtstr), expr);
             }
+
+            let comma_span = parser.prev_token.span;
             let token_expr = if let Ok(expr) = parser.parse_expr().map_err(|mut err| err.cancel()) {
                 expr
             } else {
                 return (Some(fmtstr), None);
             };
-            match &token_expr.kind {
-                ExprKind::Lit(lit)
-                    if !matches!(lit.kind, LitKind::Int(..) | LitKind::Float(..)) =>
-                {
-                    let mut all_simple = true;
-                    let mut seen = false;
-                    for arg in &args {
-                        match arg.position {
-                            ArgumentImplicitlyIs(n) | ArgumentIs(n) => {
-                                if n == idx {
-                                    all_simple &= arg.format == SIMPLE;
-                                    seen = true;
-                                }
-                            }
-                            ArgumentNamed(_) => {}
-                        }
-                    }
-                    if all_simple && seen {
-                        span_lint(cx, lint, token_expr.span, "literal with an empty format string");
-                    }
-                    idx += 1;
-                }
-                ExprKind::Assign(lhs, rhs, _) => {
-                    if_chain! {
-                        if let ExprKind::Lit(ref lit) = rhs.kind;
-                        if !matches!(lit.kind, LitKind::Int(..) | LitKind::Float(..));
-                        if let ExprKind::Path(_, p) = &lhs.kind;
-                        then {
-                            let mut all_simple = true;
-                            let mut seen = false;
-                            for arg in &args {
-                                match arg.position {
-                                    ArgumentImplicitlyIs(_) | ArgumentIs(_) => {},
-                                    ArgumentNamed(name) => {
-                                        if *p == name {
-                                            seen = true;
-                                            all_simple &= arg.format == SIMPLE;
-                                        }
-                                    },
-                                }
-                            }
-                            if all_simple && seen {
-                                span_lint(cx, lint, rhs.span, "literal with an empty format string");
-                            }
-                        }
-                    }
+            let (fmt_spans, lit) = match &token_expr.kind {
+                ExprKind::Lit(lit) => (unnamed_args.next().unwrap_or(&[]), lit),
+                ExprKind::Assign(lhs, rhs, _) => match (&lhs.kind, &rhs.kind) {
+                    (ExprKind::Path(_, p), ExprKind::Lit(lit)) => (args.get_named(p), lit),
+                    _ => continue,
+                },
+                _ => {
+                    unnamed_args.next();
+                    continue;
+                },
+            };
+
+            let replacement: String = match lit.token.kind {
+                LitKind::Integer | LitKind::Float | LitKind::Err => continue,
+                LitKind::StrRaw(_) | LitKind::ByteStrRaw(_) if matches!(fmtstr.style, StrStyle::Raw(_)) => {
+                    lit.token.symbol.as_str().replace("{", "{{").replace("}", "}}")
+                },
+                LitKind::Str | LitKind::ByteStr if matches!(fmtstr.style, StrStyle::Cooked) => {
+                    lit.token.symbol.as_str().replace("{", "{{").replace("}", "}}")
+                },
+                LitKind::StrRaw(_) | LitKind::Str | LitKind::ByteStrRaw(_) | LitKind::ByteStr => continue,
+                LitKind::Byte | LitKind::Char => match &*lit.token.symbol.as_str() {
+                    "\"" if matches!(fmtstr.style, StrStyle::Cooked) => "\\\"",
+                    "\"" if matches!(fmtstr.style, StrStyle::Raw(0)) => continue,
+                    "\\\\" if matches!(fmtstr.style, StrStyle::Raw(_)) => "\\",
+                    "\\'" => "'",
+                    "{" => "{{",
+                    "}" => "}}",
+                    x if matches!(fmtstr.style, StrStyle::Raw(_)) && x.starts_with('\\') => continue,
+                    x => x,
                 }
-                _ => idx += 1,
+                .into(),
+                LitKind::Bool => lit.token.symbol.as_str().deref().into(),
+            };
+
+            if !fmt_spans.is_empty() {
+                span_lint_and_then(
+                    cx,
+                    lint,
+                    token_expr.span,
+                    "literal with an empty format string",
+                    |diag| {
+                        diag.multipart_suggestion(
+                            "try this",
+                            iter::once((comma_span.to(token_expr.span), String::new()))
+                                .chain(fmt_spans.iter().cloned().zip(iter::repeat(replacement)))
+                                .collect(),
+                            Applicability::MachineApplicable,
+                        );
+                    },
+                );
             }
         }
     }
@@ -524,17 +609,11 @@ impl Write {
                     cx,
                     PRINT_WITH_NEWLINE,
                     mac.span(),
-                    &format!(
-                        "using `{}!()` with a format string that ends in a single newline",
-                        name
-                    ),
+                    &format!("using `{}!()` with a format string that ends in a single newline", name),
                     |err| {
                         err.multipart_suggestion(
                             &format!("use `{}!` instead", suggested),
-                            vec![
-                                (mac.path.span, suggested),
-                                (newline_span(&fmt_str), String::new()),
-                            ],
+                            vec![(mac.path.span, suggested), (newline_span(&fmt_str), String::new())],
                             Applicability::MachineApplicable,
                         );
                     },
diff --git a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
index 11d96e15ff1..3b4890ad560 100644
--- a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
@@ -1,5 +1,5 @@
 use crate::consts::{constant_simple, Constant};
-use crate::utils::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_help;
 use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
index adf7077e650..2abd033e2a0 100644
--- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
@@ -1,3 +1,6 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::paths;
+use clippy_utils::ty::{is_normalizable, is_type_diagnostic_item, match_type};
 use if_chain::if_chain;
 use rustc_hir::{self as hir, HirId, ItemKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
@@ -7,8 +10,6 @@ use rustc_span::sym;
 use rustc_target::abi::LayoutOf as _;
 use rustc_typeck::hir_ty_to_ty;
 
-use crate::utils::{is_normalizable, is_type_diagnostic_item, match_type, paths, span_lint_and_help};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for maps with zero-sized value types anywhere in the code.
     ///
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index 9e07f140cf1..d04c5f889dd 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.52"
+version = "0.1.53"
 authors = ["The Rust Clippy Developers"]
 edition = "2018"
 publish = false
@@ -10,8 +10,6 @@ if_chain = "1.0.0"
 itertools = "0.9"
 regex-syntax = "0.6"
 serde = { version = "1.0", features = ["derive"] }
-smallvec = { version = "1", features = ["union"] }
-toml = "0.5.3"
 unicode-normalization = "0.1"
 rustc-semver="1.1.0"
 
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index e202b5061a6..eaea3e636f9 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -169,9 +169,9 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
         (Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp),
         (MacCall(l), MacCall(r)) => eq_mac_call(l, r),
         (Struct(lse), Struct(rse)) => {
-            eq_path(&lse.path, &rse.path) &&
-            eq_struct_rest(&lse.rest, &rse.rest) &&
-            unordered_over(&lse.fields, &rse.fields, |l, r| eq_field(l, r))
+            eq_path(&lse.path, &rse.path)
+                && eq_struct_rest(&lse.rest, &rse.rest)
+                && unordered_over(&lse.fields, &rse.fields, |l, r| eq_field(l, r))
         },
         _ => false,
     }
@@ -409,7 +409,7 @@ pub fn eq_use_tree(l: &UseTree, r: &UseTree) -> bool {
 }
 
 pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool {
-  eq_expr(&l.value, &r.value)
+    eq_expr(&l.value, &r.value)
 }
 
 pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool {
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index ebe896b7ae8..8af10ebe777 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -15,6 +15,7 @@ use rustc_span::symbol::Symbol;
 use std::cmp::Ordering::{self, Equal};
 use std::convert::TryInto;
 use std::hash::{Hash, Hasher};
+use std::iter;
 
 /// A `LitKind`-like enum to fold constant `Expr`s into.
 #[derive(Debug, Clone)]
@@ -139,12 +140,12 @@ 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)) | (&Self::Vec(ref l), &Self::Vec(ref r)) => l
-                .iter()
-                .zip(r.iter())
-                .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::Tuple(ref l), &Self::Tuple(ref r)) | (&Self::Vec(ref l), &Self::Vec(ref r)) => {
+                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)) => {
                 match Self::partial_cmp(tcx, cmp_type, lv, rv) {
                     Some(Equal) => Some(ls.cmp(rs)),
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index 269be217c2d..e9c9cb12b9d 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -8,14 +8,16 @@ use std::env;
 
 fn docs_link(diag: &mut DiagnosticBuilder<'_>, lint: &'static Lint) {
     if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() {
-        diag.help(&format!(
-            "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{}",
-            &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| {
-                // extract just major + minor version and ignore patch versions
-                format!("rust-{}", n.rsplitn(2, '.').nth(1).unwrap())
-            }),
-            lint.name_lower().replacen("clippy::", "", 1)
-        ));
+        if let Some(lint) = lint.name_lower().strip_prefix("clippy::") {
+            diag.help(&format!(
+                "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{}",
+                &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| {
+                    // extract just major + minor version and ignore patch versions
+                    format!("rust-{}", n.rsplitn(2, '.').nth(1).unwrap())
+                }),
+                lint
+            ));
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index 8013c4e4fcb..88b115a63d7 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -9,7 +9,8 @@
 //!  - or-fun-call
 //!  - option-if-let-else
 
-use crate::{is_ctor_or_promotable_const_function, is_type_diagnostic_item};
+use crate::is_ctor_or_promotable_const_function;
+use crate::ty::is_type_diagnostic_item;
 use rustc_hir::def::{DefKind, Res};
 
 use rustc_hir::intravisit;
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 7f7d9c5f56a..618d33545a4 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -1,12 +1,13 @@
 use crate::consts::{constant_context, constant_simple};
-use crate::{differing_macro_contexts, snippet_opt};
+use crate::differing_macro_contexts;
+use crate::source::snippet_opt;
 use rustc_ast::ast::InlineAsmTemplatePiece;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::def::Res;
 use rustc_hir::{
-    BinOpKind, Block, BlockCheckMode, BodyId, BorrowKind, CaptureBy, Expr, ExprKind, ExprField, PatField, FnRetTy,
-    GenericArg, GenericArgs, Guard, HirId, InlineAsmOperand, Lifetime, LifetimeName, ParamName, Pat, PatKind, Path,
+    BinOpKind, Block, BlockCheckMode, BodyId, BorrowKind, CaptureBy, Expr, ExprField, ExprKind, FnRetTy, GenericArg,
+    GenericArgs, Guard, HirId, InlineAsmOperand, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path,
     PathSegment, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
 };
 use rustc_lexer::{tokenize, TokenKind};
@@ -79,10 +80,6 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
     pub fn eq_path_segments(&mut self, left: &[PathSegment<'_>], right: &[PathSegment<'_>]) -> bool {
         self.inter_expr().eq_path_segments(left, right)
     }
-
-    pub fn eq_ty_kind(&mut self, left: &TyKind<'_>, right: &TyKind<'_>) -> bool {
-        self.inter_expr().eq_ty_kind(left, right)
-    }
 }
 
 struct HirEqInterExpr<'a, 'b, 'tcx> {
@@ -251,7 +248,7 @@ impl HirEqInterExpr<'_, '_, '_> {
             (&ExprKind::Struct(ref l_path, ref lf, ref lo), &ExprKind::Struct(ref r_path, ref rf, ref ro)) => {
                 self.eq_qpath(l_path, r_path)
                     && both(lo, ro, |l, r| self.eq_expr(l, r))
-                    && over(lf, rf, |l, r| self.eq_field(l, r))
+                    && over(lf, rf, |l, r| self.eq_expr_field(l, r))
             },
             (&ExprKind::Tup(l_tup), &ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup),
             (&ExprKind::Unary(l_op, ref le), &ExprKind::Unary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re),
@@ -266,7 +263,7 @@ impl HirEqInterExpr<'_, '_, '_> {
         over(left, right, |l, r| self.eq_expr(l, r))
     }
 
-    fn eq_field(&mut self, left: &ExprField<'_>, right: &ExprField<'_>) -> bool {
+    fn eq_expr_field(&mut self, left: &ExprField<'_>, right: &ExprField<'_>) -> bool {
         left.ident.name == right.ident.name && self.eq_expr(&left.expr, &right.expr)
     }
 
@@ -290,7 +287,7 @@ impl HirEqInterExpr<'_, '_, '_> {
         left.name == right.name
     }
 
-    fn eq_fieldpat(&mut self, left: &PatField<'_>, right: &PatField<'_>) -> bool {
+    fn eq_pat_field(&mut self, left: &PatField<'_>, right: &PatField<'_>) -> bool {
         let (PatField { ident: li, pat: lp, .. }, PatField { ident: ri, pat: rp, .. }) = (&left, &right);
         li.name == ri.name && self.eq_pat(lp, rp)
     }
@@ -300,7 +297,7 @@ impl HirEqInterExpr<'_, '_, '_> {
         match (&left.kind, &right.kind) {
             (&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r),
             (&PatKind::Struct(ref lp, ref la, ..), &PatKind::Struct(ref rp, ref ra, ..)) => {
-                self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_fieldpat(l, r))
+                self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat_field(l, r))
             },
             (&PatKind::TupleStruct(ref lp, ref la, ls), &PatKind::TupleStruct(ref rp, ref ra, rs)) => {
                 self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs
@@ -377,13 +374,9 @@ impl HirEqInterExpr<'_, '_, '_> {
         left.ident.name == right.ident.name && both(&left.args, &right.args, |l, r| self.eq_path_parameters(l, r))
     }
 
-    fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool {
-        self.eq_ty_kind(&left.kind, &right.kind)
-    }
-
     #[allow(clippy::similar_names)]
-    fn eq_ty_kind(&mut self, left: &TyKind<'_>, right: &TyKind<'_>) -> bool {
-        match (left, right) {
+    fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool {
+        match (&left.kind, &right.kind) {
             (&TyKind::Slice(ref l_vec), &TyKind::Slice(ref r_vec)) => self.eq_ty(l_vec, r_vec),
             (&TyKind::Array(ref lt, ref ll_id), &TyKind::Array(ref rt, ref rl_id)) => {
                 let cx = self.inner.cx;
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 7d3584333af..6b235875c20 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1,5 +1,6 @@
 #![feature(box_patterns)]
 #![feature(in_band_lifetimes)]
+#![feature(iter_zip)]
 #![cfg_attr(bootstrap, feature(or_patterns))]
 #![feature(rustc_private)]
 #![recursion_limit = "512"]
@@ -32,7 +33,7 @@ pub mod attrs;
 pub mod camel_case;
 pub mod comparisons;
 pub mod consts;
-mod diagnostics;
+pub mod diagnostics;
 pub mod eager_or_lazy;
 pub mod higher;
 mod hir_utils;
@@ -40,51 +41,47 @@ pub mod numeric_literal;
 pub mod paths;
 pub mod ptr;
 pub mod qualify_min_const_fn;
+pub mod source;
 pub mod sugg;
+pub mod ty;
 pub mod usage;
 pub mod visitors;
 
 pub use self::attrs::*;
-pub use self::diagnostics::*;
 pub use self::hir_utils::{both, eq_expr_value, over, SpanlessEq, SpanlessHash};
 
-use std::borrow::Cow;
 use std::collections::hash_map::Entry;
 use std::hash::BuildHasherDefault;
 
 use if_chain::if_chain;
-use rustc_ast::ast::{self, Attribute, BorrowKind, LitKind, Mutability};
+use rustc_ast::ast::{self, Attribute, BorrowKind, LitKind};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc_hir::Node;
 use rustc_hir::{
-    def, Arm, Block, Body, Constness, Expr, ExprKind, FnDecl, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, Item,
-    ItemKind, LangItem, MatchSource, Param, Pat, PatKind, Path, PathSegment, QPath, TraitItem, TraitItemKind, TraitRef,
-    TyKind, Unsafety,
+    def, Arm, BindingAnnotation, Block, Body, Constness, Expr, ExprKind, FieldDef, FnDecl, ForeignItem, GenericArgs,
+    GenericParam, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, LangItem, Lifetime, Local, MacroDef,
+    MatchSource, Mod, Node, Param, Pat, PatKind, Path, PathSegment, QPath, Stmt, TraitItem, TraitItemKind, TraitRef,
+    TyKind, Variant, Visibility,
 };
-use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, Level, Lint, LintContext};
 use rustc_middle::hir::exports::Export;
 use rustc_middle::hir::map::Map;
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
-use rustc_middle::ty::{self, layout::IntegerExt, DefIdTree, IntTy, Ty, TyCtxt, TypeFoldable, UintTy};
+use rustc_middle::ty as rustc_ty;
+use rustc_middle::ty::{layout::IntegerExt, DefIdTree, Ty, TyCtxt, TypeFoldable};
 use rustc_semver::RustcVersion;
 use rustc_session::Session;
-use rustc_span::hygiene::{self, ExpnKind, MacroKind};
+use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::source_map::original_sp;
 use rustc_span::sym;
-use rustc_span::symbol::{kw, Symbol};
-use rustc_span::{BytePos, Pos, Span, SyntaxContext, DUMMY_SP};
+use rustc_span::symbol::{kw, Ident, Symbol};
+use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::Integer;
-use rustc_trait_selection::traits::query::normalize::AtExt;
-use smallvec::SmallVec;
 
 use crate::consts::{constant, Constant};
-use std::collections::HashMap;
+use crate::ty::is_recursively_primitive_type;
 
 pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
     if let Ok(version) = RustcVersion::parse(msrv) {
@@ -137,6 +134,58 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool {
     rhs.ctxt() != lhs.ctxt()
 }
 
+/// If the given expression is a local binding, find the initializer expression.
+/// If that initializer expression is another local binding, find its initializer again.
+/// This process repeats as long as possible (but usually no more than once). Initializer
+/// expressions with adjustments are ignored. If this is not desired, use [`find_binding_init`]
+/// instead.
+///
+/// Examples:
+/// ```ignore
+/// let abc = 1;
+/// //        ^ output
+/// let def = abc;
+/// dbg!(def)
+/// //   ^^^ input
+///
+/// // or...
+/// let abc = 1;
+/// let def = abc + 2;
+/// //        ^^^^^^^ output
+/// dbg!(def)
+/// //   ^^^ input
+/// ```
+pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr<'b>) -> &'a Expr<'b> {
+    while let Some(init) = path_to_local(expr)
+        .and_then(|id| find_binding_init(cx, id))
+        .filter(|init| cx.typeck_results().expr_adjustments(init).is_empty())
+    {
+        expr = init;
+    }
+    expr
+}
+
+/// Finds the initializer expression for a local binding. Returns `None` if the binding is mutable.
+/// By only considering immutable bindings, we guarantee that the returned expression represents the
+/// value of the binding wherever it is referenced.
+///
+/// Example: For `let x = 1`, if the `HirId` of `x` is provided, the `Expr` `1` is returned.
+/// Note: If you have an expression that references a binding `x`, use `path_to_local` to get the
+/// canonical binding `HirId`.
+pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> {
+    let hir = cx.tcx.hir();
+    if_chain! {
+        if let Some(Node::Binding(pat)) = hir.find(hir_id);
+        if matches!(pat.kind, PatKind::Binding(BindingAnnotation::Unannotated, ..));
+        let parent = hir.get_parent_node(hir_id);
+        if let Some(Node::Local(local)) = hir.find(parent);
+        then {
+            return local.init;
+        }
+    }
+    None
+}
+
 /// Returns `true` if the given `NodeId` is inside a constant context
 ///
 /// # Example
@@ -184,54 +233,11 @@ pub fn in_macro(span: Span) -> bool {
     }
 }
 
-// If the snippet is empty, it's an attribute that was inserted during macro
-// expansion and we want to ignore those, because they could come from external
-// sources that the user has no control over.
-// For some reason these attributes don't have any expansion info on them, so
-// we have to check it this way until there is a better way.
-pub fn is_present_in_source<T: LintContext>(cx: &T, span: Span) -> bool {
-    if let Some(snippet) = snippet_opt(cx, span) {
-        if snippet.is_empty() {
-            return false;
-        }
-    }
-    true
-}
-
 /// Checks if given pattern is a wildcard (`_`)
 pub fn is_wild<'tcx>(pat: &impl std::ops::Deref<Target = Pat<'tcx>>) -> bool {
     matches!(pat.kind, PatKind::Wild)
 }
 
-/// Checks if type is struct, enum or union type with the given def path.
-///
-/// If the type is a diagnostic item, use `is_type_diagnostic_item` instead.
-/// If you change the signature, remember to update the internal lint `MatchTypeOnDiagItem`
-pub fn match_type(cx: &LateContext<'_>, ty: Ty<'_>, path: &[&str]) -> bool {
-    match ty.kind() {
-        ty::Adt(adt, _) => match_def_path(cx, adt.did, path),
-        _ => false,
-    }
-}
-
-/// Checks if the type is equal to a diagnostic item
-///
-/// If you change the signature, remember to update the internal lint `MatchTypeOnDiagItem`
-pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symbol) -> bool {
-    match ty.kind() {
-        ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(diag_item, adt.did),
-        _ => false,
-    }
-}
-
-/// Checks if the type is equal to a lang item
-pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool {
-    match ty.kind() {
-        ty::Adt(adt, _) => cx.tcx.lang_items().require(lang_item).unwrap() == adt.did,
-        _ => false,
-    }
-}
-
 /// Checks if the first type parameter is a lang item.
 pub fn is_ty_param_lang_item(cx: &LateContext<'_>, qpath: &QPath<'tcx>, item: LangItem) -> Option<&'tcx hir::Ty<'tcx>> {
     let ty = get_qpath_generic_tys(qpath).next()?;
@@ -266,34 +272,37 @@ pub fn is_ty_param_diagnostic_item(
     }
 }
 
-/// Return `true` if the passed `typ` is `isize` or `usize`.
-pub fn is_isize_or_usize(typ: Ty<'_>) -> bool {
-    matches!(typ.kind(), ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize))
-}
-
 /// Checks if the method call given in `expr` belongs to the given trait.
+/// This is a deprecated function, consider using [`is_trait_method`].
 pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
     let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
     let trt_id = cx.tcx.trait_of_item(def_id);
     trt_id.map_or(false, |trt_id| match_def_path(cx, trt_id, path))
 }
 
-/// Checks if the method call given in `expr` belongs to a trait or other container with a given
+/// Checks if the method call given in `def_id` belongs to a trait or other container with a given
 /// diagnostic item
 pub fn is_diagnostic_assoc_item(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
     cx.tcx
         .opt_associated_item(def_id)
         .and_then(|associated_item| match associated_item.container {
-            ty::TraitContainer(assoc_def_id) => Some(assoc_def_id),
-            ty::ImplContainer(assoc_def_id) => match cx.tcx.type_of(assoc_def_id).kind() {
-                ty::Adt(adt, _) => Some(adt.did),
-                ty::Slice(_) => cx.tcx.get_diagnostic_item(sym::slice), // this isn't perfect but it works
+            rustc_ty::TraitContainer(assoc_def_id) => Some(assoc_def_id),
+            rustc_ty::ImplContainer(assoc_def_id) => match cx.tcx.type_of(assoc_def_id).kind() {
+                rustc_ty::Adt(adt, _) => Some(adt.did),
+                rustc_ty::Slice(_) => cx.tcx.get_diagnostic_item(sym::slice), // this isn't perfect but it works
                 _ => None,
             },
         })
         .map_or(false, |assoc_def_id| cx.tcx.is_diagnostic_item(diag_item, assoc_def_id))
 }
 
+/// Checks if the method call given in `expr` belongs to the given trait.
+pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
+    cx.typeck_results()
+        .type_dependent_def_id(expr.hir_id)
+        .map_or(false, |did| is_diagnostic_assoc_item(cx, did, diag_item))
+}
+
 /// Checks if an expression references a variable of the given name.
 pub fn match_var(expr: &Expr<'_>, var: Symbol) -> bool {
     if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.kind {
@@ -479,26 +488,6 @@ pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> {
     }
 }
 
-/// Checks whether a type implements a trait.
-/// See also `get_trait_def_id`.
-pub fn implements_trait<'tcx>(
-    cx: &LateContext<'tcx>,
-    ty: Ty<'tcx>,
-    trait_id: DefId,
-    ty_params: &[GenericArg<'tcx>],
-) -> bool {
-    // Do not check on infer_types to avoid panic in evaluate_obligation.
-    if ty.has_infer_types() {
-        return false;
-    }
-    let ty = cx.tcx.erase_regions(ty);
-    if ty.has_escaping_bound_vars() {
-        return false;
-    }
-    let ty_params = cx.tcx.mk_substs(ty_params.iter());
-    cx.tcx.type_implements_trait((trait_id, ty, ty_params, cx.param_env))
-}
-
 /// Gets the `hir::TraitRef` of the trait the given method is implemented for.
 ///
 /// Use this if you want to find the `TraitRef` of the `Add` trait in this example:
@@ -526,26 +515,6 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio
     None
 }
 
-/// Checks whether this type implements `Drop`.
-pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
-    match ty.ty_adt_def() {
-        Some(def) => def.has_dtor(cx.tcx),
-        None => false,
-    }
-}
-
-/// Checks whether a type can be partially moved.
-pub fn can_partially_move_ty(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
-    if has_drop(cx, ty) || is_copy(cx, ty) {
-        return false;
-    }
-    match ty.kind() {
-        ty::Param(_) => false,
-        ty::Adt(def, subs) => def.all_fields().any(|f| !is_copy(cx, f.ty(cx.tcx, subs))),
-        _ => true,
-    }
-}
-
 /// Returns the method names and argument list of nested method call expressions that make up
 /// `expr`. method/span lists are sorted with the most recent call first.
 pub fn method_calls<'tcx>(
@@ -727,206 +696,6 @@ pub fn find_macro_calls(names: &[&str], body: &Body<'_>) -> Vec<Span> {
     fmc.result
 }
 
-/// Converts a span to a code snippet if available, otherwise use default.
-///
-/// This is useful if you want to provide suggestions for your lint or more generally, if you want
-/// to convert a given `Span` to a `str`.
-///
-/// # Example
-/// ```rust,ignore
-/// snippet(cx, expr.span, "..")
-/// ```
-pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
-    snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from)
-}
-
-/// Same as `snippet`, but it adapts the applicability level by following rules:
-///
-/// - Applicability level `Unspecified` will never be changed.
-/// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
-/// - If the default value is used and the applicability level is `MachineApplicable`, change it to
-/// `HasPlaceholders`
-pub fn snippet_with_applicability<'a, T: LintContext>(
-    cx: &T,
-    span: Span,
-    default: &'a str,
-    applicability: &mut Applicability,
-) -> Cow<'a, str> {
-    if *applicability != Applicability::Unspecified && span.from_expansion() {
-        *applicability = Applicability::MaybeIncorrect;
-    }
-    snippet_opt(cx, span).map_or_else(
-        || {
-            if *applicability == Applicability::MachineApplicable {
-                *applicability = Applicability::HasPlaceholders;
-            }
-            Cow::Borrowed(default)
-        },
-        From::from,
-    )
-}
-
-/// Same as `snippet`, but should only be used when it's clear that the input span is
-/// not a macro argument.
-pub fn snippet_with_macro_callsite<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
-    snippet(cx, span.source_callsite(), default)
-}
-
-/// Converts a span to a code snippet. Returns `None` if not available.
-pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> {
-    cx.sess().source_map().span_to_snippet(span).ok()
-}
-
-/// Converts a span (from a block) to a code snippet if available, otherwise use default.
-///
-/// This trims the code of indentation, except for the first line. Use it for blocks or block-like
-/// things which need to be printed as such.
-///
-/// The `indent_relative_to` arg can be used, to provide a span, where the indentation of the
-/// resulting snippet of the given span.
-///
-/// # Example
-///
-/// ```rust,ignore
-/// snippet_block(cx, block.span, "..", None)
-/// // where, `block` is the block of the if expr
-///     if x {
-///         y;
-///     }
-/// // will return the snippet
-/// {
-///     y;
-/// }
-/// ```
-///
-/// ```rust,ignore
-/// snippet_block(cx, block.span, "..", Some(if_expr.span))
-/// // where, `block` is the block of the if expr
-///     if x {
-///         y;
-///     }
-/// // will return the snippet
-/// {
-///         y;
-///     } // aligned with `if`
-/// ```
-/// Note that the first line of the snippet always has 0 indentation.
-pub fn snippet_block<'a, T: LintContext>(
-    cx: &T,
-    span: Span,
-    default: &'a str,
-    indent_relative_to: Option<Span>,
-) -> Cow<'a, str> {
-    let snip = snippet(cx, span, default);
-    let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
-    reindent_multiline(snip, true, indent)
-}
-
-/// Same as `snippet_block`, but adapts the applicability level by the rules of
-/// `snippet_with_applicability`.
-pub fn snippet_block_with_applicability<'a, T: LintContext>(
-    cx: &T,
-    span: Span,
-    default: &'a str,
-    indent_relative_to: Option<Span>,
-    applicability: &mut Applicability,
-) -> Cow<'a, str> {
-    let snip = snippet_with_applicability(cx, span, default, applicability);
-    let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
-    reindent_multiline(snip, true, indent)
-}
-
-/// Same as `snippet_with_applicability`, but first walks the span up to the given context. This
-/// will result in the macro call, rather then the expansion, if the span is from a child context.
-/// If the span is not from a child context, it will be used directly instead.
-///
-/// e.g. Given the expression `&vec![]`, getting a snippet from the span for `vec![]` as a HIR node
-/// would result in `box []`. If given the context of the address of expression, this function will
-/// correctly get a snippet of `vec![]`.
-pub fn snippet_with_context(
-    cx: &LateContext<'_>,
-    span: Span,
-    outer: SyntaxContext,
-    default: &'a str,
-    applicability: &mut Applicability,
-) -> Cow<'a, str> {
-    let outer_span = hygiene::walk_chain(span, outer);
-    let span = if outer_span.ctxt() == outer {
-        outer_span
-    } else {
-        // The span is from a macro argument, and the outer context is the macro using the argument
-        if *applicability != Applicability::Unspecified {
-            *applicability = Applicability::MaybeIncorrect;
-        }
-        // TODO: get the argument span.
-        span
-    };
-
-    snippet_with_applicability(cx, span, default, applicability)
-}
-
-/// Returns a new Span that extends the original Span to the first non-whitespace char of the first
-/// line.
-///
-/// ```rust,ignore
-///     let x = ();
-/// //          ^^
-/// // will be converted to
-///     let x = ();
-/// //  ^^^^^^^^^^
-/// ```
-pub fn first_line_of_span<T: LintContext>(cx: &T, span: Span) -> Span {
-    first_char_in_first_line(cx, span).map_or(span, |first_char_pos| span.with_lo(first_char_pos))
-}
-
-fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePos> {
-    let line_span = line_span(cx, span);
-    snippet_opt(cx, line_span).and_then(|snip| {
-        snip.find(|c: char| !c.is_whitespace())
-            .map(|pos| line_span.lo() + BytePos::from_usize(pos))
-    })
-}
-
-/// Returns the indentation of the line of a span
-///
-/// ```rust,ignore
-/// let x = ();
-/// //      ^^ -- will return 0
-///     let x = ();
-/// //          ^^ -- will return 4
-/// ```
-pub fn indent_of<T: LintContext>(cx: &T, span: Span) -> Option<usize> {
-    snippet_opt(cx, line_span(cx, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace()))
-}
-
-/// Returns the positon just before rarrow
-///
-/// ```rust,ignore
-/// fn into(self) -> () {}
-///              ^
-/// // in case of unformatted code
-/// fn into2(self)-> () {}
-///               ^
-/// fn into3(self)   -> () {}
-///               ^
-/// ```
-pub fn position_before_rarrow(s: &str) -> Option<usize> {
-    s.rfind("->").map(|rpos| {
-        let mut rpos = rpos;
-        let chars: Vec<char> = s.chars().collect();
-        while rpos > 1 {
-            if let Some(c) = chars.get(rpos - 1) {
-                if c.is_whitespace() {
-                    rpos -= 1;
-                    continue;
-                }
-            }
-            break;
-        }
-        rpos
-    })
-}
-
 /// Extends the span to the beginning of the spans line, incl. whitespaces.
 ///
 /// ```rust,ignore
@@ -944,81 +713,52 @@ fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
     Span::new(line_start, span.hi(), span.ctxt())
 }
 
-/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
-/// Also takes an `Option<String>` which can be put inside the braces.
-pub fn expr_block<'a, T: LintContext>(
-    cx: &T,
-    expr: &Expr<'_>,
-    option: Option<String>,
-    default: &'a str,
-    indent_relative_to: Option<Span>,
-) -> Cow<'a, str> {
-    let code = snippet_block(cx, expr.span, default, indent_relative_to);
-    let string = option.unwrap_or_default();
-    if expr.span.from_expansion() {
-        Cow::Owned(format!("{{ {} }}", snippet_with_macro_callsite(cx, expr.span, default)))
-    } else if let ExprKind::Block(_, _) = expr.kind {
-        Cow::Owned(format!("{}{}", code, string))
-    } else if string.is_empty() {
-        Cow::Owned(format!("{{ {} }}", code))
-    } else {
-        Cow::Owned(format!("{{\n{};\n{}\n}}", code, string))
+/// Gets the span of the node, if there is one.
+pub fn get_node_span(node: Node<'_>) -> Option<Span> {
+    match node {
+        Node::Param(Param { span, .. })
+        | Node::Item(Item { span, .. })
+        | Node::ForeignItem(ForeignItem { span, .. })
+        | Node::TraitItem(TraitItem { span, .. })
+        | Node::ImplItem(ImplItem { span, .. })
+        | Node::Variant(Variant { span, .. })
+        | Node::Field(FieldDef { span, .. })
+        | Node::Expr(Expr { span, .. })
+        | Node::Stmt(Stmt { span, .. })
+        | Node::PathSegment(PathSegment {
+            ident: Ident { span, .. },
+            ..
+        })
+        | Node::Ty(hir::Ty { span, .. })
+        | Node::TraitRef(TraitRef {
+            path: Path { span, .. },
+            ..
+        })
+        | Node::Binding(Pat { span, .. })
+        | Node::Pat(Pat { span, .. })
+        | Node::Arm(Arm { span, .. })
+        | Node::Block(Block { span, .. })
+        | Node::Local(Local { span, .. })
+        | Node::MacroDef(MacroDef { span, .. })
+        | Node::Lifetime(Lifetime { span, .. })
+        | Node::GenericParam(GenericParam { span, .. })
+        | Node::Visibility(Visibility { span, .. })
+        | Node::Crate(Mod { inner: span, .. }) => Some(*span),
+        Node::Ctor(_) | Node::AnonConst(_) => None,
     }
 }
 
-/// Reindent a multiline string with possibility of ignoring the first line.
-#[allow(clippy::needless_pass_by_value)]
-pub fn reindent_multiline(s: Cow<'_, str>, ignore_first: bool, indent: Option<usize>) -> Cow<'_, str> {
-    let s_space = reindent_multiline_inner(&s, ignore_first, indent, ' ');
-    let s_tab = reindent_multiline_inner(&s_space, ignore_first, indent, '\t');
-    reindent_multiline_inner(&s_tab, ignore_first, indent, ' ').into()
-}
-
-fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option<usize>, ch: char) -> String {
-    let x = s
-        .lines()
-        .skip(ignore_first as usize)
-        .filter_map(|l| {
-            if l.is_empty() {
-                None
-            } else {
-                // ignore empty lines
-                Some(l.char_indices().find(|&(_, x)| x != ch).unwrap_or((l.len(), ch)).0)
-            }
-        })
-        .min()
-        .unwrap_or(0);
-    let indent = indent.unwrap_or(0);
-    s.lines()
-        .enumerate()
-        .map(|(i, l)| {
-            if (ignore_first && i == 0) || l.is_empty() {
-                l.to_owned()
-            } else if x > indent {
-                l.split_at(x - indent).1.to_owned()
-            } else {
-                " ".repeat(indent - x) + l
-            }
-        })
-        .collect::<Vec<String>>()
-        .join("\n")
+/// 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)
 }
 
 /// Gets the parent expression, if any –- this is useful to constrain a lint.
 pub fn get_parent_expr<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
-    let map = &cx.tcx.hir();
-    let hir_id = e.hir_id;
-    let parent_id = map.get_parent_node(hir_id);
-    if hir_id == parent_id {
-        return None;
+    match get_parent_node(cx.tcx, e.hir_id) {
+        Some(Node::Expr(parent)) => Some(parent),
+        _ => None,
     }
-    map.find(parent_id).and_then(|node| {
-        if let Node::Expr(parent) = node {
-            Some(parent)
-        } else {
-            None
-        }
-    })
 }
 
 pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Block<'tcx>> {
@@ -1058,24 +798,24 @@ pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> {
     }
 }
 
-/// Returns the base type for HIR references and pointers.
-pub fn walk_ptrs_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
-    match ty.kind {
-        TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty),
-        _ => ty,
-    }
-}
-
-/// Returns the base type for references and raw pointers, and count reference
-/// depth.
-pub fn walk_ptrs_ty_depth(ty: Ty<'_>) -> (Ty<'_>, usize) {
-    fn inner(ty: Ty<'_>, depth: usize) -> (Ty<'_>, usize) {
-        match ty.kind() {
-            ty::Ref(_, ty, _) => inner(ty, depth + 1),
-            _ => (ty, depth),
-        }
+/// Checks if the given expression is the else clause in the expression `if let .. {} else {}`
+pub fn is_else_clause_of_if_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
+    let map = tcx.hir();
+    let mut iter = map.parent_iter(expr.hir_id);
+    let arm_id = match iter.next() {
+        Some((id, Node::Arm(..))) => id,
+        _ => return false,
+    };
+    match iter.next() {
+        Some((
+            _,
+            Node::Expr(Expr {
+                kind: ExprKind::Match(_, [_, else_arm], kind),
+                ..
+            }),
+        )) => else_arm.hir_id == arm_id && matches!(kind, MatchSource::IfLetDesugar { .. }),
+        _ => false,
     }
-    inner(ty, 0)
 }
 
 /// Checks whether the given expression is a constant integer of the given value.
@@ -1173,26 +913,6 @@ pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx>
     cx.tcx.erase_late_bound_regions(ret_ty)
 }
 
-/// Walks into `ty` and returns `true` if any inner type is the same as `other_ty`
-pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool {
-    ty.walk().any(|inner| match inner.unpack() {
-        GenericArgKind::Type(inner_ty) => ty::TyS::same_type(other_ty, inner_ty),
-        GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
-    })
-}
-
-/// Returns `true` if the given type is an `unsafe` function.
-pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
-    match ty.kind() {
-        ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).unsafety() == Unsafety::Unsafe,
-        _ => false,
-    }
-}
-
-pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
-    ty.is_copy_modulo_regions(cx.tcx.at(DUMMY_SP), cx.param_env)
-}
-
 /// Checks if an expression is constructing a tuple-like enum variant or struct
 pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     if let ExprKind::Call(ref fun, _) = expr.kind {
@@ -1241,11 +961,13 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
         },
         PatKind::Slice(ref head, ref middle, ref tail) => {
             match &cx.typeck_results().node_type(pat.hir_id).kind() {
-                ty::Slice(..) => {
+                rustc_ty::Slice(..) => {
                     // [..] is the only irrefutable slice pattern.
                     !head.is_empty() || middle.is_none() || !tail.is_empty()
                 },
-                ty::Array(..) => are_refutable(cx, head.iter().chain(middle).chain(tail.iter()).map(|pat| &**pat)),
+                rustc_ty::Array(..) => {
+                    are_refutable(cx, head.iter().chain(middle).chain(tail.iter()).map(|pat| &**pat))
+                },
                 _ => {
                     // unreachable!()
                     true
@@ -1255,6 +977,16 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
     }
 }
 
+/// If the pattern is an `or` pattern, call the function once for each sub pattern. Otherwise, call
+/// the function once on the given pattern.
+pub fn recurse_or_patterns<'tcx, F: FnMut(&'tcx Pat<'tcx>)>(pat: &'tcx Pat<'tcx>, mut f: F) {
+    if let PatKind::Or(pats) = pat.kind {
+        pats.iter().cloned().for_each(f)
+    } else {
+        f(pat)
+    }
+}
+
 /// Checks for the `#[automatically_derived]` attribute all `#[derive]`d
 /// implementations have.
 pub fn is_automatically_derived(attrs: &[ast::Attribute]) -> bool {
@@ -1357,64 +1089,31 @@ pub fn strip_pat_refs<'hir>(mut pat: &'hir Pat<'hir>) -> &'hir Pat<'hir> {
     pat
 }
 
-pub fn int_bits(tcx: TyCtxt<'_>, ity: ty::IntTy) -> u64 {
+pub fn int_bits(tcx: TyCtxt<'_>, ity: rustc_ty::IntTy) -> u64 {
     Integer::from_int_ty(&tcx, ity).size().bits()
 }
 
 #[allow(clippy::cast_possible_wrap)]
 /// Turn a constant int byte representation into an i128
-pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: ty::IntTy) -> i128 {
+pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::IntTy) -> i128 {
     let amt = 128 - int_bits(tcx, ity);
     ((u as i128) << amt) >> amt
 }
 
 #[allow(clippy::cast_sign_loss)]
 /// clip unused bytes
-pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: ty::IntTy) -> u128 {
+pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: rustc_ty::IntTy) -> u128 {
     let amt = 128 - int_bits(tcx, ity);
     ((u as u128) << amt) >> amt
 }
 
 /// clip unused bytes
-pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: ty::UintTy) -> u128 {
+pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::UintTy) -> u128 {
     let bits = Integer::from_uint_ty(&tcx, ity).size().bits();
     let amt = 128 - bits;
     (u << amt) >> amt
 }
 
-/// Removes block comments from the given `Vec` of lines.
-///
-/// # Examples
-///
-/// ```rust,ignore
-/// without_block_comments(vec!["/*", "foo", "*/"]);
-/// // => vec![]
-///
-/// without_block_comments(vec!["bar", "/*", "foo", "*/"]);
-/// // => vec!["bar"]
-/// ```
-pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> {
-    let mut without = vec![];
-
-    let mut nest_level = 0;
-
-    for line in lines {
-        if line.contains("/*") {
-            nest_level += 1;
-            continue;
-        } else if line.contains("*/") {
-            nest_level -= 1;
-            continue;
-        }
-
-        if nest_level == 0 {
-            without.push(line);
-        }
-    }
-
-    without
-}
-
 pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool {
     let map = &tcx.hir();
     let mut prev_enclosing_node = None;
@@ -1429,47 +1128,6 @@ pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool
     false
 }
 
-/// Returns true if ty has `iter` or `iter_mut` methods
-pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option<Symbol> {
-    // FIXME: instead of this hard-coded list, we should check if `<adt>::iter`
-    // exists and has the desired signature. Unfortunately FnCtxt is not exported
-    // so we can't use its `lookup_method` method.
-    let into_iter_collections: &[Symbol] = &[
-        sym::vec_type,
-        sym::option_type,
-        sym::result_type,
-        sym::BTreeMap,
-        sym::BTreeSet,
-        sym::vecdeque_type,
-        sym::LinkedList,
-        sym::BinaryHeap,
-        sym::hashset_type,
-        sym::hashmap_type,
-        sym::PathBuf,
-        sym::Path,
-        sym::Receiver,
-    ];
-
-    let ty_to_check = match probably_ref_ty.kind() {
-        ty::Ref(_, ty_to_check, _) => ty_to_check,
-        _ => probably_ref_ty,
-    };
-
-    let def_id = match ty_to_check.kind() {
-        ty::Array(..) => return Some(sym::array),
-        ty::Slice(..) => return Some(sym::slice),
-        ty::Adt(adt, _) => adt.did,
-        _ => return None,
-    };
-
-    for &name in into_iter_collections {
-        if cx.tcx.is_diagnostic_item(name, def_id) {
-            return Some(cx.tcx.item_name(def_id));
-        }
-    }
-    None
-}
-
 /// Matches a function call with the given path and returns the arguments.
 ///
 /// Usage:
@@ -1494,51 +1152,6 @@ pub fn match_function_call<'tcx>(
     None
 }
 
-// FIXME: Per https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/at/struct.At.html#method.normalize
-// this function can be removed once the `normalizie` method does not panic when normalization does
-// not succeed
-/// Checks if `Ty` is normalizable. This function is useful
-/// to avoid crashes on `layout_of`.
-pub fn is_normalizable<'tcx>(cx: &LateContext<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
-    is_normalizable_helper(cx, param_env, ty, &mut HashMap::new())
-}
-
-fn is_normalizable_helper<'tcx>(
-    cx: &LateContext<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    ty: Ty<'tcx>,
-    cache: &mut HashMap<Ty<'tcx>, bool>,
-) -> bool {
-    if let Some(&cached_result) = cache.get(ty) {
-        return cached_result;
-    }
-    // prevent recursive loops, false-negative is better than endless loop leading to stack overflow
-    cache.insert(ty, false);
-    let result = cx.tcx.infer_ctxt().enter(|infcx| {
-        let cause = rustc_middle::traits::ObligationCause::dummy();
-        if infcx.at(&cause, param_env).normalize(ty).is_ok() {
-            match ty.kind() {
-                ty::Adt(def, substs) => def.variants.iter().all(|variant| {
-                    variant
-                        .fields
-                        .iter()
-                        .all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache))
-                }),
-                _ => ty.walk().all(|generic_arg| match generic_arg.unpack() {
-                    GenericArgKind::Type(inner_ty) if inner_ty != ty => {
-                        is_normalizable_helper(cx, param_env, inner_ty, cache)
-                    },
-                    _ => true, // if inner_ty == ty, we've already checked it
-                }),
-            }
-        } else {
-            false
-        }
-    });
-    cache.insert(ty, result);
-    result
-}
-
 pub fn match_def_path<'tcx>(cx: &LateContext<'tcx>, did: DefId, syms: &[&str]) -> bool {
     // We have to convert `syms` to `&[Symbol]` here because rustc's `match_def_path`
     // accepts only that. We should probably move to Symbols in Clippy as well.
@@ -1568,11 +1181,9 @@ pub fn match_panic_def_id(cx: &LateContext<'_>, did: DefId) -> bool {
 /// sequence of `if/else`.
 /// E.g., this returns `([a, b], [c, d, e])` for the expression
 /// `if a { c } else if b { d } else { e }`.
-pub fn if_sequence<'tcx>(
-    mut expr: &'tcx Expr<'tcx>,
-) -> (SmallVec<[&'tcx Expr<'tcx>; 1]>, SmallVec<[&'tcx Block<'tcx>; 1]>) {
-    let mut conds = SmallVec::new();
-    let mut blocks: SmallVec<[&Block<'_>; 1]> = SmallVec::new();
+pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>, Vec<&'tcx Block<'tcx>>) {
+    let mut conds = Vec::new();
+    let mut blocks: Vec<&Block<'_>> = Vec::new();
 
     while let ExprKind::If(ref cond, ref then_expr, ref else_expr) = expr.kind {
         conds.push(&**cond);
@@ -1624,44 +1235,6 @@ pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> {
     attr_by_name(attrs, "must_use")
 }
 
-// Returns whether the type has #[must_use] attribute
-pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
-    match ty.kind() {
-        ty::Adt(ref adt, _) => must_use_attr(&cx.tcx.get_attrs(adt.did)).is_some(),
-        ty::Foreign(ref did) => must_use_attr(&cx.tcx.get_attrs(*did)).is_some(),
-        ty::Slice(ref ty)
-        | ty::Array(ref ty, _)
-        | ty::RawPtr(ty::TypeAndMut { ref ty, .. })
-        | ty::Ref(_, ref ty, _) => {
-            // for the Array case we don't need to care for the len == 0 case
-            // because we don't want to lint functions returning empty arrays
-            is_must_use_ty(cx, *ty)
-        },
-        ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
-        ty::Opaque(ref def_id, _) => {
-            for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
-                if let ty::PredicateKind::Trait(trait_predicate, _) = predicate.kind().skip_binder() {
-                    if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() {
-                        return true;
-                    }
-                }
-            }
-            false
-        },
-        ty::Dynamic(binder, _) => {
-            for predicate in binder.iter() {
-                if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
-                    if must_use_attr(&cx.tcx.get_attrs(trait_ref.def_id)).is_some() {
-                        return true;
-                    }
-                }
-            }
-            false
-        },
-        _ => false,
-    }
-}
-
 // check if expr is calling method or function with #[must_use] attribute
 pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let did = match expr.kind {
@@ -1756,18 +1329,6 @@ pub fn run_lints(cx: &LateContext<'_>, lints: &[&'static Lint], id: HirId) -> bo
     })
 }
 
-/// Returns true iff the given type is a primitive (a bool or char, any integer or floating-point
-/// number type, a str, or an array, slice, or tuple of those types).
-pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool {
-    match ty.kind() {
-        ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => true,
-        ty::Ref(_, inner, _) if *inner.kind() == ty::Str => true,
-        ty::Array(inner_type, _) | ty::Slice(inner_type) => is_recursively_primitive_type(inner_type),
-        ty::Tuple(inner_types) => inner_types.types().all(is_recursively_primitive_type),
-        _ => false,
-    }
-}
-
 /// Returns Option<String> where String is a textual representation of the type encapsulated in the
 /// slice iff the given expression is a slice of primitives (as defined in the
 /// `is_recursively_primitive_type` function) and None otherwise.
@@ -1775,9 +1336,9 @@ pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<S
     let expr_type = cx.typeck_results().expr_ty_adjusted(expr);
     let expr_kind = expr_type.kind();
     let is_primitive = match expr_kind {
-        ty::Slice(element_type) => is_recursively_primitive_type(element_type),
-        ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), &ty::Slice(_)) => {
-            if let ty::Slice(element_type) = inner_ty.kind() {
+        rustc_ty::Slice(element_type) => is_recursively_primitive_type(element_type),
+        rustc_ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), &rustc_ty::Slice(_)) => {
+            if let rustc_ty::Slice(element_type) = inner_ty.kind() {
                 is_recursively_primitive_type(element_type)
             } else {
                 unreachable!()
@@ -1790,9 +1351,9 @@ pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<S
         // if we have wrappers like Array, Slice or Tuple, print these
         // and get the type enclosed in the slice ref
         match expr_type.peel_refs().walk().nth(1).unwrap().expect_ty().kind() {
-            ty::Slice(..) => return Some("slice".into()),
-            ty::Array(..) => return Some("array".into()),
-            ty::Tuple(..) => return Some("tuple".into()),
+            rustc_ty::Slice(..) => return Some("slice".into()),
+            rustc_ty::Array(..) => return Some("array".into()),
+            rustc_ty::Tuple(..) => return Some("tuple".into()),
             _ => {
                 // is_recursively_primitive_type() should have taken care
                 // of the rest and we can rely on the type that is found
@@ -1876,32 +1437,6 @@ pub fn peel_hir_expr_refs(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
     f(expr, 0)
 }
 
-/// Peels off all references on the type. Returns the underlying type and the number of references
-/// removed.
-pub fn peel_mid_ty_refs(ty: Ty<'_>) -> (Ty<'_>, usize) {
-    fn peel(ty: Ty<'_>, count: usize) -> (Ty<'_>, usize) {
-        if let ty::Ref(_, ty, _) = ty.kind() {
-            peel(ty, count + 1)
-        } else {
-            (ty, count)
-        }
-    }
-    peel(ty, 0)
-}
-
-/// Peels off all references on the type.Returns the underlying type, the number of references
-/// removed, and whether the pointer is ultimately mutable or not.
-pub fn peel_mid_ty_refs_is_mutable(ty: Ty<'_>) -> (Ty<'_>, usize, Mutability) {
-    fn f(ty: Ty<'_>, count: usize, mutability: Mutability) -> (Ty<'_>, usize, Mutability) {
-        match ty.kind() {
-            ty::Ref(_, ty, Mutability::Mut) => f(ty, count + 1, mutability),
-            ty::Ref(_, ty, Mutability::Not) => f(ty, count + 1, Mutability::Not),
-            _ => (ty, count, mutability),
-        }
-    }
-    f(ty, 0, Mutability::Mut)
-}
-
 #[macro_export]
 macro_rules! unwrap_cargo_metadata {
     ($cx: ident, $lint: ident, $deps: expr) => {{
@@ -1955,100 +1490,3 @@ pub fn is_some_ctor(cx: &LateContext<'_>, res: Res) -> bool {
     }
     false
 }
-
-#[cfg(test)]
-mod test {
-    use super::{reindent_multiline, without_block_comments};
-
-    #[test]
-    fn test_reindent_multiline_single_line() {
-        assert_eq!("", reindent_multiline("".into(), false, None));
-        assert_eq!("...", reindent_multiline("...".into(), false, None));
-        assert_eq!("...", reindent_multiline("    ...".into(), false, None));
-        assert_eq!("...", reindent_multiline("\t...".into(), false, None));
-        assert_eq!("...", reindent_multiline("\t\t...".into(), false, None));
-    }
-
-    #[test]
-    #[rustfmt::skip]
-    fn test_reindent_multiline_block() {
-        assert_eq!("\
-    if x {
-        y
-    } else {
-        z
-    }", reindent_multiline("    if x {
-            y
-        } else {
-            z
-        }".into(), false, None));
-        assert_eq!("\
-    if x {
-    \ty
-    } else {
-    \tz
-    }", reindent_multiline("    if x {
-        \ty
-        } else {
-        \tz
-        }".into(), false, None));
-    }
-
-    #[test]
-    #[rustfmt::skip]
-    fn test_reindent_multiline_empty_line() {
-        assert_eq!("\
-    if x {
-        y
-
-    } else {
-        z
-    }", reindent_multiline("    if x {
-            y
-
-        } else {
-            z
-        }".into(), false, None));
-    }
-
-    #[test]
-    #[rustfmt::skip]
-    fn test_reindent_multiline_lines_deeper() {
-        assert_eq!("\
-        if x {
-            y
-        } else {
-            z
-        }", reindent_multiline("\
-    if x {
-        y
-    } else {
-        z
-    }".into(), true, Some(8)));
-    }
-
-    #[test]
-    fn test_without_block_comments_lines_without_block_comments() {
-        let result = without_block_comments(vec!["/*", "", "*/"]);
-        println!("result: {:?}", result);
-        assert!(result.is_empty());
-
-        let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]);
-        assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]);
-
-        let result = without_block_comments(vec!["/* rust", "", "*/"]);
-        assert!(result.is_empty());
-
-        let result = without_block_comments(vec!["/* one-line comment */"]);
-        assert!(result.is_empty());
-
-        let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]);
-        assert!(result.is_empty());
-
-        let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]);
-        assert!(result.is_empty());
-
-        let result = without_block_comments(vec!["foo", "bar", "baz"]);
-        assert_eq!(result, vec!["foo", "bar", "baz"]);
-    }
-}
diff --git a/src/tools/clippy/clippy_utils/src/numeric_literal.rs b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
index d02603d7702..268bc5b3205 100644
--- a/src/tools/clippy/clippy_utils/src/numeric_literal.rs
+++ b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
@@ -1,4 +1,5 @@
 use rustc_ast::ast::{Lit, LitFloatType, LitIntType, LitKind};
+use std::iter;
 
 #[derive(Debug, PartialEq, Copy, Clone)]
 pub enum Radix {
@@ -192,7 +193,7 @@ impl<'a> NumericLiteral<'a> {
             }
         }
 
-        for (c, i) in digits.zip((0..group_size).cycle()) {
+        for (c, i) in iter::zip(digits, (0..group_size).cycle()) {
             if i == 0 {
                 output.push('_');
             }
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 560614efc74..11a446e42a4 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -61,7 +61,6 @@ pub const IO_READ: [&str; 3] = ["std", "io", "Read"];
 pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"];
 pub const IPADDR_V4: [&str; 4] = ["std", "net", "IpAddr", "V4"];
 pub const IPADDR_V6: [&str; 4] = ["std", "net", "IpAddr", "V6"];
-pub const ITERATOR: [&str; 5] = ["core", "iter", "traits", "iterator", "Iterator"];
 #[cfg(feature = "internal-lints")]
 pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"];
 #[cfg(feature = "internal-lints")]
diff --git a/src/tools/clippy/clippy_utils/src/ptr.rs b/src/tools/clippy/clippy_utils/src/ptr.rs
index df6143edbca..5885cc83560 100644
--- a/src/tools/clippy/clippy_utils/src/ptr.rs
+++ b/src/tools/clippy/clippy_utils/src/ptr.rs
@@ -1,4 +1,5 @@
-use crate::{get_pat_name, match_var, snippet};
+use crate::source::snippet;
+use crate::{get_pat_name, match_var};
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
 use rustc_hir::{Body, BodyId, Expr, ExprKind, Param};
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs
new file mode 100644
index 00000000000..2d794d48dc5
--- /dev/null
+++ b/src/tools/clippy/clippy_utils/src/source.rs
@@ -0,0 +1,420 @@
+//! Utils for extracting, inspecting or transforming source code
+
+#![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::{BytePos, Pos, Span, SyntaxContext};
+use std::borrow::Cow;
+
+/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
+/// Also takes an `Option<String>` which can be put inside the braces.
+pub fn expr_block<'a, T: LintContext>(
+    cx: &T,
+    expr: &Expr<'_>,
+    option: Option<String>,
+    default: &'a str,
+    indent_relative_to: Option<Span>,
+) -> Cow<'a, str> {
+    let code = snippet_block(cx, expr.span, default, indent_relative_to);
+    let string = option.unwrap_or_default();
+    if expr.span.from_expansion() {
+        Cow::Owned(format!("{{ {} }}", snippet_with_macro_callsite(cx, expr.span, default)))
+    } else if let ExprKind::Block(_, _) = expr.kind {
+        Cow::Owned(format!("{}{}", code, string))
+    } else if string.is_empty() {
+        Cow::Owned(format!("{{ {} }}", code))
+    } else {
+        Cow::Owned(format!("{{\n{};\n{}\n}}", code, string))
+    }
+}
+
+/// Returns a new Span that extends the original Span to the first non-whitespace char of the first
+/// line.
+///
+/// ```rust,ignore
+///     let x = ();
+/// //          ^^
+/// // will be converted to
+///     let x = ();
+/// //  ^^^^^^^^^^
+/// ```
+pub fn first_line_of_span<T: LintContext>(cx: &T, span: Span) -> Span {
+    first_char_in_first_line(cx, span).map_or(span, |first_char_pos| span.with_lo(first_char_pos))
+}
+
+fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePos> {
+    let line_span = line_span(cx, span);
+    snippet_opt(cx, line_span).and_then(|snip| {
+        snip.find(|c: char| !c.is_whitespace())
+            .map(|pos| line_span.lo() + BytePos::from_usize(pos))
+    })
+}
+
+/// Returns the indentation of the line of a span
+///
+/// ```rust,ignore
+/// let x = ();
+/// //      ^^ -- will return 0
+///     let x = ();
+/// //          ^^ -- will return 4
+/// ```
+pub fn indent_of<T: LintContext>(cx: &T, span: Span) -> Option<usize> {
+    snippet_opt(cx, line_span(cx, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace()))
+}
+
+// If the snippet is empty, it's an attribute that was inserted during macro
+// expansion and we want to ignore those, because they could come from external
+// sources that the user has no control over.
+// For some reason these attributes don't have any expansion info on them, so
+// we have to check it this way until there is a better way.
+pub fn is_present_in_source<T: LintContext>(cx: &T, span: Span) -> bool {
+    if let Some(snippet) = snippet_opt(cx, span) {
+        if snippet.is_empty() {
+            return false;
+        }
+    }
+    true
+}
+
+/// Returns the positon just before rarrow
+///
+/// ```rust,ignore
+/// fn into(self) -> () {}
+///              ^
+/// // in case of unformatted code
+/// fn into2(self)-> () {}
+///               ^
+/// fn into3(self)   -> () {}
+///               ^
+/// ```
+pub fn position_before_rarrow(s: &str) -> Option<usize> {
+    s.rfind("->").map(|rpos| {
+        let mut rpos = rpos;
+        let chars: Vec<char> = s.chars().collect();
+        while rpos > 1 {
+            if let Some(c) = chars.get(rpos - 1) {
+                if c.is_whitespace() {
+                    rpos -= 1;
+                    continue;
+                }
+            }
+            break;
+        }
+        rpos
+    })
+}
+
+/// Reindent a multiline string with possibility of ignoring the first line.
+#[allow(clippy::needless_pass_by_value)]
+pub fn reindent_multiline(s: Cow<'_, str>, ignore_first: bool, indent: Option<usize>) -> Cow<'_, str> {
+    let s_space = reindent_multiline_inner(&s, ignore_first, indent, ' ');
+    let s_tab = reindent_multiline_inner(&s_space, ignore_first, indent, '\t');
+    reindent_multiline_inner(&s_tab, ignore_first, indent, ' ').into()
+}
+
+fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option<usize>, ch: char) -> String {
+    let x = s
+        .lines()
+        .skip(ignore_first as usize)
+        .filter_map(|l| {
+            if l.is_empty() {
+                None
+            } else {
+                // ignore empty lines
+                Some(l.char_indices().find(|&(_, x)| x != ch).unwrap_or((l.len(), ch)).0)
+            }
+        })
+        .min()
+        .unwrap_or(0);
+    let indent = indent.unwrap_or(0);
+    s.lines()
+        .enumerate()
+        .map(|(i, l)| {
+            if (ignore_first && i == 0) || l.is_empty() {
+                l.to_owned()
+            } else if x > indent {
+                l.split_at(x - indent).1.to_owned()
+            } else {
+                " ".repeat(indent - x) + l
+            }
+        })
+        .collect::<Vec<String>>()
+        .join("\n")
+}
+
+/// Converts a span to a code snippet if available, otherwise use default.
+///
+/// This is useful if you want to provide suggestions for your lint or more generally, if you want
+/// to convert a given `Span` to a `str`.
+///
+/// # Example
+/// ```rust,ignore
+/// snippet(cx, expr.span, "..")
+/// ```
+pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
+    snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from)
+}
+
+/// Same as `snippet`, but it adapts the applicability level by following rules:
+///
+/// - Applicability level `Unspecified` will never be changed.
+/// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
+/// - If the default value is used and the applicability level is `MachineApplicable`, change it to
+/// `HasPlaceholders`
+pub fn snippet_with_applicability<'a, T: LintContext>(
+    cx: &T,
+    span: Span,
+    default: &'a str,
+    applicability: &mut Applicability,
+) -> Cow<'a, str> {
+    if *applicability != Applicability::Unspecified && span.from_expansion() {
+        *applicability = Applicability::MaybeIncorrect;
+    }
+    snippet_opt(cx, span).map_or_else(
+        || {
+            if *applicability == Applicability::MachineApplicable {
+                *applicability = Applicability::HasPlaceholders;
+            }
+            Cow::Borrowed(default)
+        },
+        From::from,
+    )
+}
+
+/// Same as `snippet`, but should only be used when it's clear that the input span is
+/// not a macro argument.
+pub fn snippet_with_macro_callsite<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
+    snippet(cx, span.source_callsite(), default)
+}
+
+/// Converts a span to a code snippet. Returns `None` if not available.
+pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> {
+    cx.sess().source_map().span_to_snippet(span).ok()
+}
+
+/// Converts a span (from a block) to a code snippet if available, otherwise use default.
+///
+/// This trims the code of indentation, except for the first line. Use it for blocks or block-like
+/// things which need to be printed as such.
+///
+/// The `indent_relative_to` arg can be used, to provide a span, where the indentation of the
+/// resulting snippet of the given span.
+///
+/// # Example
+///
+/// ```rust,ignore
+/// snippet_block(cx, block.span, "..", None)
+/// // where, `block` is the block of the if expr
+///     if x {
+///         y;
+///     }
+/// // will return the snippet
+/// {
+///     y;
+/// }
+/// ```
+///
+/// ```rust,ignore
+/// snippet_block(cx, block.span, "..", Some(if_expr.span))
+/// // where, `block` is the block of the if expr
+///     if x {
+///         y;
+///     }
+/// // will return the snippet
+/// {
+///         y;
+///     } // aligned with `if`
+/// ```
+/// Note that the first line of the snippet always has 0 indentation.
+pub fn snippet_block<'a, T: LintContext>(
+    cx: &T,
+    span: Span,
+    default: &'a str,
+    indent_relative_to: Option<Span>,
+) -> Cow<'a, str> {
+    let snip = snippet(cx, span, default);
+    let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
+    reindent_multiline(snip, true, indent)
+}
+
+/// Same as `snippet_block`, but adapts the applicability level by the rules of
+/// `snippet_with_applicability`.
+pub fn snippet_block_with_applicability<'a, T: LintContext>(
+    cx: &T,
+    span: Span,
+    default: &'a str,
+    indent_relative_to: Option<Span>,
+    applicability: &mut Applicability,
+) -> Cow<'a, str> {
+    let snip = snippet_with_applicability(cx, span, default, applicability);
+    let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
+    reindent_multiline(snip, true, indent)
+}
+
+/// Same as `snippet_with_applicability`, but first walks the span up to the given context. This
+/// will result in the macro call, rather then the expansion, if the span is from a child context.
+/// If the span is not from a child context, it will be used directly instead.
+///
+/// e.g. Given the expression `&vec![]`, getting a snippet from the span for `vec![]` as a HIR node
+/// would result in `box []`. If given the context of the address of expression, this function will
+/// correctly get a snippet of `vec![]`.
+///
+/// This will also return whether or not the snippet is a macro call.
+pub fn snippet_with_context(
+    cx: &LateContext<'_>,
+    span: Span,
+    outer: SyntaxContext,
+    default: &'a str,
+    applicability: &mut Applicability,
+) -> (Cow<'a, str>, bool) {
+    let outer_span = hygiene::walk_chain(span, outer);
+    let (span, is_macro_call) = if outer_span.ctxt() == outer {
+        (outer_span, span.ctxt() != outer)
+    } else {
+        // The span is from a macro argument, and the outer context is the macro using the argument
+        if *applicability != Applicability::Unspecified {
+            *applicability = Applicability::MaybeIncorrect;
+        }
+        // TODO: get the argument span.
+        (span, false)
+    };
+
+    (
+        snippet_with_applicability(cx, span, default, applicability),
+        is_macro_call,
+    )
+}
+
+/// Removes block comments from the given `Vec` of lines.
+///
+/// # Examples
+///
+/// ```rust,ignore
+/// without_block_comments(vec!["/*", "foo", "*/"]);
+/// // => vec![]
+///
+/// without_block_comments(vec!["bar", "/*", "foo", "*/"]);
+/// // => vec!["bar"]
+/// ```
+pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> {
+    let mut without = vec![];
+
+    let mut nest_level = 0;
+
+    for line in lines {
+        if line.contains("/*") {
+            nest_level += 1;
+            continue;
+        } else if line.contains("*/") {
+            nest_level -= 1;
+            continue;
+        }
+
+        if nest_level == 0 {
+            without.push(line);
+        }
+    }
+
+    without
+}
+
+#[cfg(test)]
+mod test {
+    use super::{reindent_multiline, without_block_comments};
+
+    #[test]
+    fn test_reindent_multiline_single_line() {
+        assert_eq!("", reindent_multiline("".into(), false, None));
+        assert_eq!("...", reindent_multiline("...".into(), false, None));
+        assert_eq!("...", reindent_multiline("    ...".into(), false, None));
+        assert_eq!("...", reindent_multiline("\t...".into(), false, None));
+        assert_eq!("...", reindent_multiline("\t\t...".into(), false, None));
+    }
+
+    #[test]
+    #[rustfmt::skip]
+    fn test_reindent_multiline_block() {
+        assert_eq!("\
+    if x {
+        y
+    } else {
+        z
+    }", reindent_multiline("    if x {
+            y
+        } else {
+            z
+        }".into(), false, None));
+        assert_eq!("\
+    if x {
+    \ty
+    } else {
+    \tz
+    }", reindent_multiline("    if x {
+        \ty
+        } else {
+        \tz
+        }".into(), false, None));
+    }
+
+    #[test]
+    #[rustfmt::skip]
+    fn test_reindent_multiline_empty_line() {
+        assert_eq!("\
+    if x {
+        y
+
+    } else {
+        z
+    }", reindent_multiline("    if x {
+            y
+
+        } else {
+            z
+        }".into(), false, None));
+    }
+
+    #[test]
+    #[rustfmt::skip]
+    fn test_reindent_multiline_lines_deeper() {
+        assert_eq!("\
+        if x {
+            y
+        } else {
+            z
+        }", reindent_multiline("\
+    if x {
+        y
+    } else {
+        z
+    }".into(), true, Some(8)));
+    }
+
+    #[test]
+    fn test_without_block_comments_lines_without_block_comments() {
+        let result = without_block_comments(vec!["/*", "", "*/"]);
+        println!("result: {:?}", result);
+        assert!(result.is_empty());
+
+        let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]);
+        assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]);
+
+        let result = without_block_comments(vec!["/* rust", "", "*/"]);
+        assert!(result.is_empty());
+
+        let result = without_block_comments(vec!["/* one-line comment */"]);
+        assert!(result.is_empty());
+
+        let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]);
+        assert!(result.is_empty());
+
+        let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]);
+        assert!(result.is_empty());
+
+        let result = without_block_comments(vec!["foo", "bar", "baz"]);
+        assert_eq!(result, vec!["foo", "bar", "baz"]);
+    }
+}
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index d4f6f4281d3..b2fe4317154 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -1,7 +1,8 @@
 //! Contains utility functions to generate suggestions.
 #![deny(clippy::missing_docs_in_private_items)]
 
-use crate::{higher, snippet, snippet_opt, snippet_with_macro_callsite};
+use crate::higher;
+use crate::source::{snippet, snippet_opt, snippet_with_macro_callsite};
 use rustc_ast::util::parser::AssocOp;
 use rustc_ast::{ast, token};
 use rustc_ast_pretty::pprust::token_kind_to_string;
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
new file mode 100644
index 00000000000..807cfbc4c7f
--- /dev/null
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -0,0 +1,305 @@
+//! Util methods for [`rustc_middle::ty`]
+
+#![allow(clippy::module_name_repetitions)]
+
+use std::collections::HashMap;
+
+use rustc_ast::ast::Mutability;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::{TyKind, Unsafety};
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_lint::LateContext;
+use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
+use rustc_middle::ty::{self, AdtDef, IntTy, Ty, TypeFoldable, UintTy};
+use rustc_span::sym;
+use rustc_span::symbol::Symbol;
+use rustc_span::DUMMY_SP;
+use rustc_trait_selection::traits::query::normalize::AtExt;
+
+use crate::{match_def_path, must_use_attr};
+
+pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+    ty.is_copy_modulo_regions(cx.tcx.at(DUMMY_SP), cx.param_env)
+}
+
+/// Checks whether a type can be partially moved.
+pub fn can_partially_move_ty(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+    if has_drop(cx, ty) || is_copy(cx, ty) {
+        return false;
+    }
+    match ty.kind() {
+        ty::Param(_) => false,
+        ty::Adt(def, subs) => def.all_fields().any(|f| !is_copy(cx, f.ty(cx.tcx, subs))),
+        _ => true,
+    }
+}
+
+/// Walks into `ty` and returns `true` if any inner type is the same as `other_ty`
+pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool {
+    ty.walk().any(|inner| match inner.unpack() {
+        GenericArgKind::Type(inner_ty) => ty::TyS::same_type(other_ty, inner_ty),
+        GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
+    })
+}
+
+/// Walks into `ty` and returns `true` if any inner type is an instance of the given adt
+/// constructor.
+pub fn contains_adt_constructor(ty: Ty<'_>, adt: &AdtDef) -> bool {
+    ty.walk().any(|inner| match inner.unpack() {
+        GenericArgKind::Type(inner_ty) => inner_ty.ty_adt_def() == Some(adt),
+        GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
+    })
+}
+
+/// Returns true if ty has `iter` or `iter_mut` methods
+pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option<Symbol> {
+    // FIXME: instead of this hard-coded list, we should check if `<adt>::iter`
+    // exists and has the desired signature. Unfortunately FnCtxt is not exported
+    // so we can't use its `lookup_method` method.
+    let into_iter_collections: &[Symbol] = &[
+        sym::vec_type,
+        sym::option_type,
+        sym::result_type,
+        sym::BTreeMap,
+        sym::BTreeSet,
+        sym::vecdeque_type,
+        sym::LinkedList,
+        sym::BinaryHeap,
+        sym::hashset_type,
+        sym::hashmap_type,
+        sym::PathBuf,
+        sym::Path,
+        sym::Receiver,
+    ];
+
+    let ty_to_check = match probably_ref_ty.kind() {
+        ty::Ref(_, ty_to_check, _) => ty_to_check,
+        _ => probably_ref_ty,
+    };
+
+    let def_id = match ty_to_check.kind() {
+        ty::Array(..) => return Some(sym::array),
+        ty::Slice(..) => return Some(sym::slice),
+        ty::Adt(adt, _) => adt.did,
+        _ => return None,
+    };
+
+    for &name in into_iter_collections {
+        if cx.tcx.is_diagnostic_item(name, def_id) {
+            return Some(cx.tcx.item_name(def_id));
+        }
+    }
+    None
+}
+
+/// Checks whether a type implements a trait.
+/// See also `get_trait_def_id`.
+pub fn implements_trait<'tcx>(
+    cx: &LateContext<'tcx>,
+    ty: Ty<'tcx>,
+    trait_id: DefId,
+    ty_params: &[GenericArg<'tcx>],
+) -> bool {
+    // Do not check on infer_types to avoid panic in evaluate_obligation.
+    if ty.has_infer_types() {
+        return false;
+    }
+    let ty = cx.tcx.erase_regions(ty);
+    if ty.has_escaping_bound_vars() {
+        return false;
+    }
+    let ty_params = cx.tcx.mk_substs(ty_params.iter());
+    cx.tcx.type_implements_trait((trait_id, ty, ty_params, cx.param_env))
+}
+
+/// Checks whether this type implements `Drop`.
+pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+    match ty.ty_adt_def() {
+        Some(def) => def.has_dtor(cx.tcx),
+        None => false,
+    }
+}
+
+// Returns whether the type has #[must_use] attribute
+pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+    match ty.kind() {
+        ty::Adt(ref adt, _) => must_use_attr(&cx.tcx.get_attrs(adt.did)).is_some(),
+        ty::Foreign(ref did) => must_use_attr(&cx.tcx.get_attrs(*did)).is_some(),
+        ty::Slice(ref ty)
+        | ty::Array(ref ty, _)
+        | ty::RawPtr(ty::TypeAndMut { ref ty, .. })
+        | ty::Ref(_, ref ty, _) => {
+            // for the Array case we don't need to care for the len == 0 case
+            // because we don't want to lint functions returning empty arrays
+            is_must_use_ty(cx, *ty)
+        },
+        ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
+        ty::Opaque(ref def_id, _) => {
+            for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
+                if let ty::PredicateKind::Trait(trait_predicate, _) = predicate.kind().skip_binder() {
+                    if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() {
+                        return true;
+                    }
+                }
+            }
+            false
+        },
+        ty::Dynamic(binder, _) => {
+            for predicate in binder.iter() {
+                if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
+                    if must_use_attr(&cx.tcx.get_attrs(trait_ref.def_id)).is_some() {
+                        return true;
+                    }
+                }
+            }
+            false
+        },
+        _ => false,
+    }
+}
+
+// FIXME: Per https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/at/struct.At.html#method.normalize
+// this function can be removed once the `normalizie` method does not panic when normalization does
+// not succeed
+/// Checks if `Ty` is normalizable. This function is useful
+/// to avoid crashes on `layout_of`.
+pub fn is_normalizable<'tcx>(cx: &LateContext<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
+    is_normalizable_helper(cx, param_env, ty, &mut HashMap::new())
+}
+
+fn is_normalizable_helper<'tcx>(
+    cx: &LateContext<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    ty: Ty<'tcx>,
+    cache: &mut HashMap<Ty<'tcx>, bool>,
+) -> bool {
+    if let Some(&cached_result) = cache.get(ty) {
+        return cached_result;
+    }
+    // prevent recursive loops, false-negative is better than endless loop leading to stack overflow
+    cache.insert(ty, false);
+    let result = cx.tcx.infer_ctxt().enter(|infcx| {
+        let cause = rustc_middle::traits::ObligationCause::dummy();
+        if infcx.at(&cause, param_env).normalize(ty).is_ok() {
+            match ty.kind() {
+                ty::Adt(def, substs) => def.variants.iter().all(|variant| {
+                    variant
+                        .fields
+                        .iter()
+                        .all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache))
+                }),
+                _ => ty.walk().all(|generic_arg| match generic_arg.unpack() {
+                    GenericArgKind::Type(inner_ty) if inner_ty != ty => {
+                        is_normalizable_helper(cx, param_env, inner_ty, cache)
+                    },
+                    _ => true, // if inner_ty == ty, we've already checked it
+                }),
+            }
+        } else {
+            false
+        }
+    });
+    cache.insert(ty, result);
+    result
+}
+
+/// Returns true iff the given type is a primitive (a bool or char, any integer or floating-point
+/// number type, a str, or an array, slice, or tuple of those types).
+pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool {
+    match ty.kind() {
+        ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => true,
+        ty::Ref(_, inner, _) if *inner.kind() == ty::Str => true,
+        ty::Array(inner_type, _) | ty::Slice(inner_type) => is_recursively_primitive_type(inner_type),
+        ty::Tuple(inner_types) => inner_types.types().all(is_recursively_primitive_type),
+        _ => false,
+    }
+}
+
+/// Checks if the type is equal to a diagnostic item
+///
+/// If you change the signature, remember to update the internal lint `MatchTypeOnDiagItem`
+pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symbol) -> bool {
+    match ty.kind() {
+        ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(diag_item, adt.did),
+        _ => false,
+    }
+}
+
+/// Checks if the type is equal to a lang item
+pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool {
+    match ty.kind() {
+        ty::Adt(adt, _) => cx.tcx.lang_items().require(lang_item).unwrap() == adt.did,
+        _ => false,
+    }
+}
+
+/// Return `true` if the passed `typ` is `isize` or `usize`.
+pub fn is_isize_or_usize(typ: Ty<'_>) -> bool {
+    matches!(typ.kind(), ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize))
+}
+
+/// Checks if type is struct, enum or union type with the given def path.
+///
+/// If the type is a diagnostic item, use `is_type_diagnostic_item` instead.
+/// If you change the signature, remember to update the internal lint `MatchTypeOnDiagItem`
+pub fn match_type(cx: &LateContext<'_>, ty: Ty<'_>, path: &[&str]) -> bool {
+    match ty.kind() {
+        ty::Adt(adt, _) => match_def_path(cx, adt.did, path),
+        _ => false,
+    }
+}
+
+/// Peels off all references on the type. Returns the underlying type and the number of references
+/// removed.
+pub fn peel_mid_ty_refs(ty: Ty<'_>) -> (Ty<'_>, usize) {
+    fn peel(ty: Ty<'_>, count: usize) -> (Ty<'_>, usize) {
+        if let ty::Ref(_, ty, _) = ty.kind() {
+            peel(ty, count + 1)
+        } else {
+            (ty, count)
+        }
+    }
+    peel(ty, 0)
+}
+
+/// Peels off all references on the type.Returns the underlying type, the number of references
+/// removed, and whether the pointer is ultimately mutable or not.
+pub fn peel_mid_ty_refs_is_mutable(ty: Ty<'_>) -> (Ty<'_>, usize, Mutability) {
+    fn f(ty: Ty<'_>, count: usize, mutability: Mutability) -> (Ty<'_>, usize, Mutability) {
+        match ty.kind() {
+            ty::Ref(_, ty, Mutability::Mut) => f(ty, count + 1, mutability),
+            ty::Ref(_, ty, Mutability::Not) => f(ty, count + 1, Mutability::Not),
+            _ => (ty, count, mutability),
+        }
+    }
+    f(ty, 0, Mutability::Mut)
+}
+
+/// Returns `true` if the given type is an `unsafe` function.
+pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+    match ty.kind() {
+        ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).unsafety() == Unsafety::Unsafe,
+        _ => false,
+    }
+}
+
+/// Returns the base type for HIR references and pointers.
+pub fn walk_ptrs_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
+    match ty.kind {
+        TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty),
+        _ => ty,
+    }
+}
+
+/// Returns the base type for references and raw pointers, and count reference
+/// depth.
+pub fn walk_ptrs_ty_depth(ty: Ty<'_>) -> (Ty<'_>, usize) {
+    fn inner(ty: Ty<'_>, depth: usize) -> (Ty<'_>, usize) {
+        match ty.kind() {
+            ty::Ref(_, ty, _) => inner(ty, depth + 1),
+            _ => (ty, depth),
+        }
+    }
+    inner(ty, 0)
+}
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index 0b1ab6b7ea1..54f110988d7 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -7,8 +7,8 @@ use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
 use rustc_hir::{Expr, ExprKind, HirId, Path};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
-use rustc_middle::mir::FakeReadCause;
 use rustc_middle::hir::map::Map;
+use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty;
 use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
@@ -79,7 +79,7 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
         self.update(&cmt)
     }
 
-    fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _:HirId) { }
+    fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) {}
 }
 
 pub struct ParamBindingIdCollector {
diff --git a/src/tools/clippy/doc/basics.md b/src/tools/clippy/doc/basics.md
index c56e84e2e32..5226875cc21 100644
--- a/src/tools/clippy/doc/basics.md
+++ b/src/tools/clippy/doc/basics.md
@@ -88,8 +88,8 @@ cargo dev fmt
 cargo dev update_lints
 # create a new lint and register it
 cargo dev new_lint
-# (experimental) Setup Clippy to work with rust-analyzer
-cargo dev ra_setup
+# (experimental) Setup Clippy to work with IntelliJ-Rust
+cargo dev ide_setup
 ```
 
 ## lintcheck
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index c52a7f2e743..c2821f31fd7 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-03-11"
+channel = "nightly-2021-03-25"
 components = ["llvm-tools-preview", "rustc-dev", "rust-src"]
diff --git a/src/tools/clippy/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs b/src/tools/clippy/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs
index 735909887ac..c6659edacc3 100644
--- a/src/tools/clippy/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs
+++ b/src/tools/clippy/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs
@@ -20,4 +20,9 @@ enum Flags {
 // `GccLlvmSomething`
 struct GCCLLVMSomething;
 
+// don't warn on public items
+pub struct MIXEDCapital;
+
+pub struct FULLCAPITAL;
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/def_id_nocore.stderr b/src/tools/clippy/tests/ui/def_id_nocore.stderr
index ed87a50547d..702684f6b43 100644
--- a/src/tools/clippy/tests/ui/def_id_nocore.stderr
+++ b/src/tools/clippy/tests/ui/def_id_nocore.stderr
@@ -1,10 +1,11 @@
-error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name
+error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
   --> $DIR/def_id_nocore.rs:26:19
    |
 LL |     pub fn as_ref(self) -> &'static str {
    |                   ^^^^
    |
    = note: `-D clippy::wrong-self-convention` implied by `-D warnings`
+   = help: consider choosing a less ambiguous name
 
 error: aborting due to previous error
 
diff --git a/src/tools/clippy/tests/ui/dereference.stderr b/src/tools/clippy/tests/ui/dereference.stderr
deleted file mode 100644
index d26b462a433..00000000000
--- a/src/tools/clippy/tests/ui/dereference.stderr
+++ /dev/null
@@ -1,70 +0,0 @@
-error: explicit deref method call
-  --> $DIR/dereference.rs:30:19
-   |
-LL |     let b: &str = a.deref();
-   |                   ^^^^^^^^^ help: try this: `&*a`
-   |
-   = note: `-D clippy::explicit-deref-methods` implied by `-D warnings`
-
-error: explicit deref_mut method call
-  --> $DIR/dereference.rs:32:23
-   |
-LL |     let b: &mut str = a.deref_mut();
-   |                       ^^^^^^^^^^^^^ help: try this: `&mut *a`
-
-error: explicit deref method call
-  --> $DIR/dereference.rs:35:39
-   |
-LL |     let b: String = format!("{}, {}", a.deref(), a.deref());
-   |                                       ^^^^^^^^^ help: try this: `&*a`
-
-error: explicit deref method call
-  --> $DIR/dereference.rs:35:50
-   |
-LL |     let b: String = format!("{}, {}", a.deref(), a.deref());
-   |                                                  ^^^^^^^^^ help: try this: `&*a`
-
-error: explicit deref method call
-  --> $DIR/dereference.rs:37:20
-   |
-LL |     println!("{}", a.deref());
-   |                    ^^^^^^^^^ help: try this: `&*a`
-
-error: explicit deref method call
-  --> $DIR/dereference.rs:40:11
-   |
-LL |     match a.deref() {
-   |           ^^^^^^^^^ help: try this: `&*a`
-
-error: explicit deref method call
-  --> $DIR/dereference.rs:44:28
-   |
-LL |     let b: String = concat(a.deref());
-   |                            ^^^^^^^^^ help: try this: `&*a`
-
-error: explicit deref method call
-  --> $DIR/dereference.rs:46:13
-   |
-LL |     let b = just_return(a).deref();
-   |             ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*just_return(a)`
-
-error: explicit deref method call
-  --> $DIR/dereference.rs:48:28
-   |
-LL |     let b: String = concat(just_return(a).deref());
-   |                            ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*just_return(a)`
-
-error: explicit deref method call
-  --> $DIR/dereference.rs:50:19
-   |
-LL |     let b: &str = a.deref().deref();
-   |                   ^^^^^^^^^^^^^^^^^ help: try this: `&*a.deref()`
-
-error: explicit deref method call
-  --> $DIR/dereference.rs:53:13
-   |
-LL |     let b = opt_a.unwrap().deref();
-   |             ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()`
-
-error: aborting due to 11 previous errors
-
diff --git a/src/tools/clippy/tests/ui/dereference.fixed b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
index 459ca91b93b..51d0468e47c 100644
--- a/src/tools/clippy/tests/ui/dereference.fixed
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
@@ -29,7 +29,7 @@ fn main() {
 
     let b: &str = &*a;
 
-    let b: &mut str = &mut *a;
+    let b: &mut str = &mut **a;
 
     // both derefs should get linted here
     let b: String = format!("{}, {}", &*a, &*a);
@@ -43,11 +43,11 @@ fn main() {
 
     let b: String = concat(&*a);
 
-    let b = &*just_return(a);
+    let b = just_return(a);
 
-    let b: String = concat(&*just_return(a));
+    let b: String = concat(just_return(a));
 
-    let b: &str = &*a.deref();
+    let b: &str = &**a;
 
     let opt_a = Some(a.clone());
     let b = &*opt_a.unwrap();
@@ -76,6 +76,8 @@ fn main() {
     }
     let b: &str = expr_deref!(a);
 
+    let b: &str = expr_deref!(&*a);
+
     // The struct does not implement Deref trait
     #[derive(Copy, Clone)]
     struct NoLint(u32);
diff --git a/src/tools/clippy/tests/ui/dereference.rs b/src/tools/clippy/tests/ui/explicit_deref_methods.rs
index 8dc5272e67f..680664bd4f6 100644
--- a/src/tools/clippy/tests/ui/dereference.rs
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.rs
@@ -76,6 +76,8 @@ fn main() {
     }
     let b: &str = expr_deref!(a);
 
+    let b: &str = expr_deref!(a.deref());
+
     // The struct does not implement Deref trait
     #[derive(Copy, Clone)]
     struct NoLint(u32);
diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.stderr b/src/tools/clippy/tests/ui/explicit_deref_methods.stderr
new file mode 100644
index 00000000000..8035d77d18d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.stderr
@@ -0,0 +1,76 @@
+error: explicit `deref` method call
+  --> $DIR/explicit_deref_methods.rs:30:19
+   |
+LL |     let b: &str = a.deref();
+   |                   ^^^^^^^^^ help: try this: `&*a`
+   |
+   = note: `-D clippy::explicit-deref-methods` implied by `-D warnings`
+
+error: explicit `deref_mut` method call
+  --> $DIR/explicit_deref_methods.rs:32:23
+   |
+LL |     let b: &mut str = a.deref_mut();
+   |                       ^^^^^^^^^^^^^ help: try this: `&mut **a`
+
+error: explicit `deref` method call
+  --> $DIR/explicit_deref_methods.rs:35:39
+   |
+LL |     let b: String = format!("{}, {}", a.deref(), a.deref());
+   |                                       ^^^^^^^^^ help: try this: `&*a`
+
+error: explicit `deref` method call
+  --> $DIR/explicit_deref_methods.rs:35:50
+   |
+LL |     let b: String = format!("{}, {}", a.deref(), a.deref());
+   |                                                  ^^^^^^^^^ help: try this: `&*a`
+
+error: explicit `deref` method call
+  --> $DIR/explicit_deref_methods.rs:37:20
+   |
+LL |     println!("{}", a.deref());
+   |                    ^^^^^^^^^ help: try this: `&*a`
+
+error: explicit `deref` method call
+  --> $DIR/explicit_deref_methods.rs:40:11
+   |
+LL |     match a.deref() {
+   |           ^^^^^^^^^ help: try this: `&*a`
+
+error: explicit `deref` method call
+  --> $DIR/explicit_deref_methods.rs:44:28
+   |
+LL |     let b: String = concat(a.deref());
+   |                            ^^^^^^^^^ help: try this: `&*a`
+
+error: explicit `deref` method call
+  --> $DIR/explicit_deref_methods.rs:46:13
+   |
+LL |     let b = just_return(a).deref();
+   |             ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)`
+
+error: explicit `deref` method call
+  --> $DIR/explicit_deref_methods.rs:48:28
+   |
+LL |     let b: String = concat(just_return(a).deref());
+   |                            ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)`
+
+error: explicit `deref` method call
+  --> $DIR/explicit_deref_methods.rs:50:19
+   |
+LL |     let b: &str = a.deref().deref();
+   |                   ^^^^^^^^^^^^^^^^^ help: try this: `&**a`
+
+error: explicit `deref` method call
+  --> $DIR/explicit_deref_methods.rs:53:13
+   |
+LL |     let b = opt_a.unwrap().deref();
+   |             ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()`
+
+error: explicit `deref` method call
+  --> $DIR/explicit_deref_methods.rs:79:31
+   |
+LL |     let b: &str = expr_deref!(a.deref());
+   |                               ^^^^^^^^^ help: try this: `&*a`
+
+error: aborting due to 12 previous errors
+
diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.rs b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
index 9fc208f5332..1368c5d7984 100644
--- a/src/tools/clippy/tests/ui/field_reassign_with_default.rs
+++ b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
@@ -136,6 +136,13 @@ fn main() {
 
     // Don't lint in external macros
     field_reassign_with_default!();
+
+    // be sure suggestion is correct with generics
+    let mut a: Wrapper<bool> = Default::default();
+    a.i = true;
+
+    let mut a: WrapperMulti<i32, i64> = Default::default();
+    a.i = 42;
 }
 
 mod m {
@@ -145,3 +152,14 @@ mod m {
         b: u64,
     }
 }
+
+#[derive(Default)]
+struct Wrapper<T> {
+    i: T,
+}
+
+#[derive(Default)]
+struct WrapperMulti<T, U> {
+    i: T,
+    j: U,
+}
diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
index 2f0f28f7bb7..dd7c0360bb1 100644
--- a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
+++ b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
@@ -83,5 +83,29 @@ note: consider initializing the variable with `C { i: vec![1], ..Default::defaul
 LL |     let mut a: C = C::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: field assignment outside of initializer for an instance created with Default::default()
+  --> $DIR/field_reassign_with_default.rs:142:5
+   |
+LL |     a.i = true;
+   |     ^^^^^^^^^^^
+   |
+note: consider initializing the variable with `Wrapper::<bool> { i: true }` and removing relevant reassignments
+  --> $DIR/field_reassign_with_default.rs:141:5
+   |
+LL |     let mut a: Wrapper<bool> = Default::default();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: field assignment outside of initializer for an instance created with Default::default()
+  --> $DIR/field_reassign_with_default.rs:145:5
+   |
+LL |     a.i = 42;
+   |     ^^^^^^^^^
+   |
+note: consider initializing the variable with `WrapperMulti::<i32, i64> { i: 42, ..Default::default() }` and removing relevant reassignments
+  --> $DIR/field_reassign_with_default.rs:144:5
+   |
+LL |     let mut a: WrapperMulti<i32, i64> = Default::default();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/if_then_some_else_none.rs b/src/tools/clippy/tests/ui/if_then_some_else_none.rs
new file mode 100644
index 00000000000..54789bf9320
--- /dev/null
+++ b/src/tools/clippy/tests/ui/if_then_some_else_none.rs
@@ -0,0 +1,104 @@
+#![warn(clippy::if_then_some_else_none)]
+#![feature(custom_inner_attributes)]
+
+fn main() {
+    // Should issue an error.
+    let _ = if foo() {
+        println!("true!");
+        Some("foo")
+    } else {
+        None
+    };
+
+    // Should issue an error when macros are used.
+    let _ = if matches!(true, true) {
+        println!("true!");
+        Some(matches!(true, false))
+    } else {
+        None
+    };
+
+    // Should issue an error. Binary expression `o < 32` should be parenthesized.
+    let x = Some(5);
+    let _ = x.and_then(|o| if o < 32 { Some(o) } else { None });
+
+    // Should issue an error. Unary expression `!x` should be parenthesized.
+    let x = true;
+    let _ = if !x { Some(0) } else { None };
+
+    // Should not issue an error since the `else` block has a statement besides `None`.
+    let _ = if foo() {
+        println!("true!");
+        Some("foo")
+    } else {
+        eprintln!("false...");
+        None
+    };
+
+    // Should not issue an error since there are more than 2 blocks in the if-else chain.
+    let _ = if foo() {
+        println!("foo true!");
+        Some("foo")
+    } else if bar() {
+        println!("bar true!");
+        Some("bar")
+    } else {
+        None
+    };
+
+    let _ = if foo() {
+        println!("foo true!");
+        Some("foo")
+    } else {
+        bar().then(|| {
+            println!("bar true!");
+            "bar"
+        })
+    };
+
+    // Should not issue an error since the `then` block has `None`, not `Some`.
+    let _ = if foo() { None } else { Some("foo is false") };
+
+    // Should not issue an error since the `else` block doesn't use `None` directly.
+    let _ = if foo() { Some("foo is true") } else { into_none() };
+
+    // Should not issue an error since the `then` block doesn't use `Some` directly.
+    let _ = if foo() { into_some("foo") } else { None };
+}
+
+fn _msrv_1_49() {
+    #![clippy::msrv = "1.49"]
+    // `bool::then` was stabilized in 1.50. Do not lint this
+    let _ = if foo() {
+        println!("true!");
+        Some(149)
+    } else {
+        None
+    };
+}
+
+fn _msrv_1_50() {
+    #![clippy::msrv = "1.50"]
+    let _ = if foo() {
+        println!("true!");
+        Some(150)
+    } else {
+        None
+    };
+}
+
+fn foo() -> bool {
+    unimplemented!()
+}
+
+fn bar() -> bool {
+    unimplemented!()
+}
+
+fn into_some<T>(v: T) -> Option<T> {
+    Some(v)
+}
+
+fn into_none<T>() -> Option<T> {
+    None
+}
diff --git a/src/tools/clippy/tests/ui/if_then_some_else_none.stderr b/src/tools/clippy/tests/ui/if_then_some_else_none.stderr
new file mode 100644
index 00000000000..8cb22d569f4
--- /dev/null
+++ b/src/tools/clippy/tests/ui/if_then_some_else_none.stderr
@@ -0,0 +1,61 @@
+error: this could be simplified with `bool::then`
+  --> $DIR/if_then_some_else_none.rs:6:13
+   |
+LL |       let _ = if foo() {
+   |  _____________^
+LL | |         println!("true!");
+LL | |         Some("foo")
+LL | |     } else {
+LL | |         None
+LL | |     };
+   | |_____^
+   |
+   = note: `-D clippy::if-then-some-else-none` implied by `-D warnings`
+   = help: consider using `bool::then` like: `foo().then(|| { /* snippet */ "foo" })`
+
+error: this could be simplified with `bool::then`
+  --> $DIR/if_then_some_else_none.rs:14:13
+   |
+LL |       let _ = if matches!(true, true) {
+   |  _____________^
+LL | |         println!("true!");
+LL | |         Some(matches!(true, false))
+LL | |     } else {
+LL | |         None
+LL | |     };
+   | |_____^
+   |
+   = help: consider using `bool::then` like: `matches!(true, true).then(|| { /* snippet */ matches!(true, false) })`
+
+error: this could be simplified with `bool::then`
+  --> $DIR/if_then_some_else_none.rs:23:28
+   |
+LL |     let _ = x.and_then(|o| if o < 32 { Some(o) } else { None });
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using `bool::then` like: `(o < 32).then(|| o)`
+
+error: this could be simplified with `bool::then`
+  --> $DIR/if_then_some_else_none.rs:27:13
+   |
+LL |     let _ = if !x { Some(0) } else { None };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using `bool::then` like: `(!x).then(|| 0)`
+
+error: this could be simplified with `bool::then`
+  --> $DIR/if_then_some_else_none.rs:82:13
+   |
+LL |       let _ = if foo() {
+   |  _____________^
+LL | |         println!("true!");
+LL | |         Some(150)
+LL | |     } else {
+LL | |         None
+LL | |     };
+   | |_____^
+   |
+   = help: consider using `bool::then` like: `foo().then(|| { /* snippet */ 150 })`
+
+error: aborting due to 5 previous errors
+
diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr
index d7abe44f254..d021bb19579 100644
--- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr
+++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr
@@ -1,4 +1,4 @@
-error: inconsistent struct constructor
+error: struct constructor field order is inconsistent with struct definition field order
   --> $DIR/inconsistent_struct_constructor.rs:25:9
    |
 LL |         Foo { y, x, z };
@@ -6,7 +6,7 @@ LL |         Foo { y, x, z };
    |
    = note: `-D clippy::inconsistent-struct-constructor` implied by `-D warnings`
 
-error: inconsistent struct constructor
+error: struct constructor field order is inconsistent with struct definition field order
   --> $DIR/inconsistent_struct_constructor.rs:43:9
    |
 LL | /         Foo {
diff --git a/src/tools/clippy/tests/ui/manual_flatten.rs b/src/tools/clippy/tests/ui/manual_flatten.rs
index cff68eca933..b5bd35a6878 100644
--- a/src/tools/clippy/tests/ui/manual_flatten.rs
+++ b/src/tools/clippy/tests/ui/manual_flatten.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::manual_flatten)]
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // Test for loop over implicitly adjusted `Iterator` with `if let` expression
@@ -69,6 +70,27 @@ fn main() {
         }
     }
 
+    let vec_of_ref = vec![&Some(1)];
+    for n in &vec_of_ref {
+        if let Some(n) = n {
+            println!("{:?}", n);
+        }
+    }
+
+    let vec_of_ref = &vec_of_ref;
+    for n in vec_of_ref {
+        if let Some(n) = n {
+            println!("{:?}", n);
+        }
+    }
+
+    let slice_of_ref = &[&Some(1)];
+    for n in slice_of_ref {
+        if let Some(n) = n {
+            println!("{:?}", n);
+        }
+    }
+
     // Using manual flatten should not trigger the lint
     for n in vec![Some(1), Some(2), Some(3)].iter().flatten() {
         println!("{}", n);
diff --git a/src/tools/clippy/tests/ui/manual_flatten.stderr b/src/tools/clippy/tests/ui/manual_flatten.stderr
index 855dd9130e2..be5f8a1d818 100644
--- a/src/tools/clippy/tests/ui/manual_flatten.stderr
+++ b/src/tools/clippy/tests/ui/manual_flatten.stderr
@@ -1,5 +1,5 @@
 error: unnecessary `if let` since only the `Some` variant of the iterator element is used
-  --> $DIR/manual_flatten.rs:6:5
+  --> $DIR/manual_flatten.rs:7:5
    |
 LL |       for n in x {
    |       ^        - help: try: `x.into_iter().flatten()`
@@ -13,7 +13,7 @@ LL | |     }
    |
    = note: `-D clippy::manual-flatten` implied by `-D warnings`
 help: ...and remove the `if let` statement in the for loop
-  --> $DIR/manual_flatten.rs:7:9
+  --> $DIR/manual_flatten.rs:8:9
    |
 LL | /         if let Some(y) = n {
 LL | |             println!("{}", y);
@@ -21,7 +21,7 @@ LL | |         }
    | |_________^
 
 error: unnecessary `if let` since only the `Ok` variant of the iterator element is used
-  --> $DIR/manual_flatten.rs:14:5
+  --> $DIR/manual_flatten.rs:15:5
    |
 LL |       for n in y.clone() {
    |       ^        --------- help: try: `y.clone().into_iter().flatten()`
@@ -34,7 +34,7 @@ LL | |     }
    | |_____^
    |
 help: ...and remove the `if let` statement in the for loop
-  --> $DIR/manual_flatten.rs:15:9
+  --> $DIR/manual_flatten.rs:16:9
    |
 LL | /         if let Ok(n) = n {
 LL | |             println!("{}", n);
@@ -42,7 +42,7 @@ LL | |         };
    | |_________^
 
 error: unnecessary `if let` since only the `Ok` variant of the iterator element is used
-  --> $DIR/manual_flatten.rs:21:5
+  --> $DIR/manual_flatten.rs:22:5
    |
 LL |       for n in &y {
    |       ^        -- help: try: `y.iter().flatten()`
@@ -55,7 +55,7 @@ LL | |     }
    | |_____^
    |
 help: ...and remove the `if let` statement in the for loop
-  --> $DIR/manual_flatten.rs:22:9
+  --> $DIR/manual_flatten.rs:23:9
    |
 LL | /         if let Ok(n) = n {
 LL | |             println!("{}", n);
@@ -63,7 +63,7 @@ LL | |         }
    | |_________^
 
 error: unnecessary `if let` since only the `Ok` variant of the iterator element is used
-  --> $DIR/manual_flatten.rs:31:5
+  --> $DIR/manual_flatten.rs:32:5
    |
 LL |       for n in z {
    |       ^        - help: try: `z.into_iter().flatten()`
@@ -76,7 +76,7 @@ LL | |     }
    | |_____^
    |
 help: ...and remove the `if let` statement in the for loop
-  --> $DIR/manual_flatten.rs:32:9
+  --> $DIR/manual_flatten.rs:33:9
    |
 LL | /         if let Ok(n) = n {
 LL | |             println!("{}", n);
@@ -84,7 +84,7 @@ LL | |         }
    | |_________^
 
 error: unnecessary `if let` since only the `Some` variant of the iterator element is used
-  --> $DIR/manual_flatten.rs:40:5
+  --> $DIR/manual_flatten.rs:41:5
    |
 LL |       for n in z {
    |       ^        - help: try: `z.flatten()`
@@ -97,12 +97,75 @@ LL | |     }
    | |_____^
    |
 help: ...and remove the `if let` statement in the for loop
-  --> $DIR/manual_flatten.rs:41:9
+  --> $DIR/manual_flatten.rs:42:9
    |
 LL | /         if let Some(m) = n {
 LL | |             println!("{}", m);
 LL | |         }
    | |_________^
 
-error: aborting due to 5 previous errors
+error: unnecessary `if let` since only the `Some` variant of the iterator element is used
+  --> $DIR/manual_flatten.rs:74:5
+   |
+LL |       for n in &vec_of_ref {
+   |       ^        ----------- help: try: `vec_of_ref.iter().copied().flatten()`
+   |  _____|
+   | |
+LL | |         if let Some(n) = n {
+LL | |             println!("{:?}", n);
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: ...and remove the `if let` statement in the for loop
+  --> $DIR/manual_flatten.rs:75:9
+   |
+LL | /         if let Some(n) = n {
+LL | |             println!("{:?}", n);
+LL | |         }
+   | |_________^
+
+error: unnecessary `if let` since only the `Some` variant of the iterator element is used
+  --> $DIR/manual_flatten.rs:81:5
+   |
+LL |       for n in vec_of_ref {
+   |       ^        ---------- help: try: `vec_of_ref.into_iter().copied().flatten()`
+   |  _____|
+   | |
+LL | |         if let Some(n) = n {
+LL | |             println!("{:?}", n);
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: ...and remove the `if let` statement in the for loop
+  --> $DIR/manual_flatten.rs:82:9
+   |
+LL | /         if let Some(n) = n {
+LL | |             println!("{:?}", n);
+LL | |         }
+   | |_________^
+
+error: unnecessary `if let` since only the `Some` variant of the iterator element is used
+  --> $DIR/manual_flatten.rs:88:5
+   |
+LL |       for n in slice_of_ref {
+   |       ^        ------------ help: try: `slice_of_ref.into_iter().copied().flatten()`
+   |  _____|
+   | |
+LL | |         if let Some(n) = n {
+LL | |             println!("{:?}", n);
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: ...and remove the `if let` statement in the for loop
+  --> $DIR/manual_flatten.rs:89:9
+   |
+LL | /         if let Some(n) = n {
+LL | |             println!("{:?}", n);
+LL | |         }
+   | |_________^
+
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_map_option.fixed b/src/tools/clippy/tests/ui/manual_map_option.fixed
index 9222aaf6c78..acb6a580ceb 100644
--- a/src/tools/clippy/tests/ui/manual_map_option.fixed
+++ b/src/tools/clippy/tests/ui/manual_map_option.fixed
@@ -128,4 +128,9 @@ fn main() {
             None => None,
         };
     }
+
+    // #6847
+    if Some(0).is_some() {
+        Some(0)
+    } else { Some(0).map(|x| x + 1) };
 }
diff --git a/src/tools/clippy/tests/ui/manual_map_option.rs b/src/tools/clippy/tests/ui/manual_map_option.rs
index 1ccb450619c..3299e617707 100644
--- a/src/tools/clippy/tests/ui/manual_map_option.rs
+++ b/src/tools/clippy/tests/ui/manual_map_option.rs
@@ -186,4 +186,13 @@ fn main() {
             None => None,
         };
     }
+
+    // #6847
+    if let Some(_) = Some(0) {
+        Some(0)
+    } else if let Some(x) = Some(0) {
+        Some(x + 1)
+    } else {
+        None
+    };
 }
diff --git a/src/tools/clippy/tests/ui/manual_map_option.stderr b/src/tools/clippy/tests/ui/manual_map_option.stderr
index d9f86eecd93..048ccfb9582 100644
--- a/src/tools/clippy/tests/ui/manual_map_option.stderr
+++ b/src/tools/clippy/tests/ui/manual_map_option.stderr
@@ -172,5 +172,24 @@ LL | |         None => None,
 LL | |     };
    | |_____^ help: try this: `option_env!("").map(String::from)`
 
-error: aborting due to 19 previous errors
+error: redundant pattern matching, consider using `is_some()`
+  --> $DIR/manual_map_option.rs:191:12
+   |
+LL |     if let Some(_) = Some(0) {
+   |     -------^^^^^^^---------- help: try this: `if Some(0).is_some()`
+   |
+   = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
+
+error: manual implementation of `Option::map`
+  --> $DIR/manual_map_option.rs:193:12
+   |
+LL |       } else if let Some(x) = Some(0) {
+   |  ____________^
+LL | |         Some(x + 1)
+LL | |     } else {
+LL | |         None
+LL | |     };
+   | |_____^ help: try this: `{ Some(0).map(|x| x + 1) }`
+
+error: aborting due to 21 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
index 81d903c15d3..f1d3252230b 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
@@ -136,4 +136,19 @@ fn result_unwrap_or() {
     };
 }
 
+// don't lint in const fn
+const fn const_fn_option_unwrap_or() {
+    match Some(1) {
+        Some(s) => s,
+        None => 0,
+    };
+}
+
+const fn const_fn_result_unwrap_or() {
+    match Ok::<&str, &str>("Alice") {
+        Ok(s) => s,
+        Err(_) => "Bob",
+    };
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.rs b/src/tools/clippy/tests/ui/manual_unwrap_or.rs
index 16105d379c3..c9eee25a5b1 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.rs
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.rs
@@ -175,4 +175,19 @@ fn result_unwrap_or() {
     };
 }
 
+// don't lint in const fn
+const fn const_fn_option_unwrap_or() {
+    match Some(1) {
+        Some(s) => s,
+        None => 0,
+    };
+}
+
+const fn const_fn_result_unwrap_or() {
+    match Ok::<&str, &str>("Alice") {
+        Ok(s) => s,
+        Err(_) => "Bob",
+    };
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/match_single_binding2.fixed b/src/tools/clippy/tests/ui/match_single_binding2.fixed
new file mode 100644
index 00000000000..e73a85b73d7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/match_single_binding2.fixed
@@ -0,0 +1,37 @@
+// run-rustfix
+
+#![warn(clippy::match_single_binding)]
+#![allow(unused_variables)]
+
+fn main() {
+    // Lint (additional curly braces needed, see #6572)
+    struct AppendIter<I>
+    where
+        I: Iterator,
+    {
+        inner: Option<(I, <I as Iterator>::Item)>,
+    }
+
+    #[allow(dead_code)]
+    fn size_hint<I: Iterator>(iter: &AppendIter<I>) -> (usize, Option<usize>) {
+        match &iter.inner {
+            Some((iter, _item)) => {
+                let (min, max) = iter.size_hint();
+                (min.saturating_add(1), max.and_then(|max| max.checked_add(1)))
+            },
+            None => (0, Some(0)),
+        }
+    }
+
+    // Lint (no additional curly braces needed)
+    let opt = Some((5, 2));
+    let get_tup = || -> (i32, i32) { (1, 2) };
+    match opt {
+        #[rustfmt::skip]
+        Some((first, _second)) => {
+            let (a, b) = get_tup();
+            println!("a {:?} and b {:?}", a, b);
+        },
+        None => println!("nothing"),
+    }
+}
diff --git a/src/tools/clippy/tests/ui/match_single_binding2.rs b/src/tools/clippy/tests/ui/match_single_binding2.rs
new file mode 100644
index 00000000000..7362cb390e5
--- /dev/null
+++ b/src/tools/clippy/tests/ui/match_single_binding2.rs
@@ -0,0 +1,37 @@
+// run-rustfix
+
+#![warn(clippy::match_single_binding)]
+#![allow(unused_variables)]
+
+fn main() {
+    // Lint (additional curly braces needed, see #6572)
+    struct AppendIter<I>
+    where
+        I: Iterator,
+    {
+        inner: Option<(I, <I as Iterator>::Item)>,
+    }
+
+    #[allow(dead_code)]
+    fn size_hint<I: Iterator>(iter: &AppendIter<I>) -> (usize, Option<usize>) {
+        match &iter.inner {
+            Some((iter, _item)) => match iter.size_hint() {
+                (min, max) => (min.saturating_add(1), max.and_then(|max| max.checked_add(1))),
+            },
+            None => (0, Some(0)),
+        }
+    }
+
+    // Lint (no additional curly braces needed)
+    let opt = Some((5, 2));
+    let get_tup = || -> (i32, i32) { (1, 2) };
+    match opt {
+        #[rustfmt::skip]
+        Some((first, _second)) => {
+            match get_tup() {
+                (a, b) => println!("a {:?} and b {:?}", a, b),
+            }
+        },
+        None => println!("nothing"),
+    }
+}
diff --git a/src/tools/clippy/tests/ui/match_single_binding2.stderr b/src/tools/clippy/tests/ui/match_single_binding2.stderr
new file mode 100644
index 00000000000..bc18d191aa3
--- /dev/null
+++ b/src/tools/clippy/tests/ui/match_single_binding2.stderr
@@ -0,0 +1,34 @@
+error: this match could be written as a `let` statement
+  --> $DIR/match_single_binding2.rs:18:36
+   |
+LL |               Some((iter, _item)) => match iter.size_hint() {
+   |  ____________________________________^
+LL | |                 (min, max) => (min.saturating_add(1), max.and_then(|max| max.checked_add(1))),
+LL | |             },
+   | |_____________^
+   |
+   = note: `-D clippy::match-single-binding` implied by `-D warnings`
+help: consider using `let` statement
+   |
+LL |             Some((iter, _item)) => {
+LL |                 let (min, max) = iter.size_hint();
+LL |                 (min.saturating_add(1), max.and_then(|max| max.checked_add(1)))
+LL |             },
+   |
+
+error: this match could be written as a `let` statement
+  --> $DIR/match_single_binding2.rs:31:13
+   |
+LL | /             match get_tup() {
+LL | |                 (a, b) => println!("a {:?} and b {:?}", a, b),
+LL | |             }
+   | |_____________^
+   |
+help: consider using `let` statement
+   |
+LL |             let (a, b) = get_tup();
+LL |             println!("a {:?} and b {:?}", a, b);
+   |
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
index 519200977a7..d99f9af3faf 100644
--- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
+++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
@@ -15,6 +15,16 @@ enum Color {
     Blue,
     Rgb(u8, u8, u8),
 }
+impl Color {
+    fn f(self) {
+        match self {
+            Self::Red => (),
+            Self::Green => (),
+            Self::Blue => (),
+            Self::Rgb(..) => (),
+        };
+    }
+}
 
 fn main() {
     let f = Foo::A;
@@ -56,4 +66,46 @@ fn main() {
         Color::Rgb(255, _, _) => {},
         _ => {},
     }
+
+    // References shouldn't change anything
+    match &color {
+        &Color::Red => (),
+        Color::Green => (),
+        &Color::Rgb(..) => (),
+        Color::Blue => (),
+    }
+
+    use self::Color as C;
+
+    match color {
+        C::Red => (),
+        C::Green => (),
+        C::Rgb(..) => (),
+        C::Blue => (),
+    }
+
+    match color {
+        C::Red => (),
+        Color::Green => (),
+        Color::Rgb(..) => (),
+        Color::Blue => (),
+    }
+
+    match Some(0) {
+        Some(0) => 0,
+        Some(_) => 1,
+        _ => 2,
+    };
+
+    #[non_exhaustive]
+    enum Bar {
+        A,
+        B,
+        C,
+    }
+    match Bar::A {
+        Bar::A => (),
+        Bar::B => (),
+        _ => (),
+    };
 }
diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs
index 1df917e085c..1752a95de4b 100644
--- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs
+++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs
@@ -15,6 +15,16 @@ enum Color {
     Blue,
     Rgb(u8, u8, u8),
 }
+impl Color {
+    fn f(self) {
+        match self {
+            Self::Red => (),
+            Self::Green => (),
+            Self::Blue => (),
+            _ => (),
+        };
+    }
+}
 
 fn main() {
     let f = Foo::A;
@@ -56,4 +66,46 @@ fn main() {
         Color::Rgb(255, _, _) => {},
         _ => {},
     }
+
+    // References shouldn't change anything
+    match &color {
+        &Color::Red => (),
+        Color::Green => (),
+        &Color::Rgb(..) => (),
+        &_ => (),
+    }
+
+    use self::Color as C;
+
+    match color {
+        C::Red => (),
+        C::Green => (),
+        C::Rgb(..) => (),
+        _ => (),
+    }
+
+    match color {
+        C::Red => (),
+        Color::Green => (),
+        Color::Rgb(..) => (),
+        _ => (),
+    }
+
+    match Some(0) {
+        Some(0) => 0,
+        Some(_) => 1,
+        _ => 2,
+    };
+
+    #[non_exhaustive]
+    enum Bar {
+        A,
+        B,
+        C,
+    }
+    match Bar::A {
+        Bar::A => (),
+        Bar::B => (),
+        _ => (),
+    };
 }
diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr
index 82790aa9e80..34538dea8e5 100644
--- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr
+++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr
@@ -1,28 +1,52 @@
-error: wildcard match will miss any future added variants
-  --> $DIR/match_wildcard_for_single_variants.rs:24:9
+error: wildcard matches only a single variant and will also match any future added variants
+  --> $DIR/match_wildcard_for_single_variants.rs:24:13
    |
-LL |         _ => {},
-   |         ^ help: try this: `Foo::C`
+LL |             _ => (),
+   |             ^ help: try this: `Self::Rgb(..)`
    |
    = note: `-D clippy::match-wildcard-for-single-variants` implied by `-D warnings`
 
-error: wildcard match will miss any future added variants
+error: wildcard matches only a single variant and will also match any future added variants
   --> $DIR/match_wildcard_for_single_variants.rs:34:9
    |
 LL |         _ => {},
+   |         ^ help: try this: `Foo::C`
+
+error: wildcard matches only a single variant and will also match any future added variants
+  --> $DIR/match_wildcard_for_single_variants.rs:44:9
+   |
+LL |         _ => {},
    |         ^ help: try this: `Color::Blue`
 
-error: wildcard match will miss any future added variants
-  --> $DIR/match_wildcard_for_single_variants.rs:42:9
+error: wildcard matches only a single variant and will also match any future added variants
+  --> $DIR/match_wildcard_for_single_variants.rs:52:9
    |
 LL |         _ => {},
    |         ^ help: try this: `Color::Blue`
 
-error: wildcard match will miss any future added variants
-  --> $DIR/match_wildcard_for_single_variants.rs:48:9
+error: wildcard matches only a single variant and will also match any future added variants
+  --> $DIR/match_wildcard_for_single_variants.rs:58:9
    |
 LL |         _ => {},
    |         ^ help: try this: `Color::Blue`
 
-error: aborting due to 4 previous errors
+error: wildcard matches only a single variant and will also match any future added variants
+  --> $DIR/match_wildcard_for_single_variants.rs:75:9
+   |
+LL |         &_ => (),
+   |         ^^ help: try this: `Color::Blue`
+
+error: wildcard matches only a single variant and will also match any future added variants
+  --> $DIR/match_wildcard_for_single_variants.rs:84:9
+   |
+LL |         _ => (),
+   |         ^ help: try this: `C::Blue`
+
+error: wildcard matches only a single variant and will also match any future added variants
+  --> $DIR/match_wildcard_for_single_variants.rs:91:9
+   |
+LL |         _ => (),
+   |         ^ help: try this: `Color::Blue`
+
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/mem_replace.fixed b/src/tools/clippy/tests/ui/mem_replace.fixed
index 54e962e7116..3b6224254a0 100644
--- a/src/tools/clippy/tests/ui/mem_replace.fixed
+++ b/src/tools/clippy/tests/ui/mem_replace.fixed
@@ -7,6 +7,7 @@
     clippy::mem_replace_with_default
 )]
 
+use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
 use std::mem;
 
 fn replace_option_with_none() {
@@ -19,9 +20,37 @@ fn replace_option_with_none() {
 fn replace_with_default() {
     let mut s = String::from("foo");
     let _ = std::mem::take(&mut s);
+
     let s = &mut String::from("foo");
     let _ = std::mem::take(s);
     let _ = std::mem::take(s);
+
+    let mut v = vec![123];
+    let _ = std::mem::take(&mut v);
+    let _ = std::mem::take(&mut v);
+    let _ = std::mem::take(&mut v);
+    let _ = std::mem::take(&mut v);
+
+    let mut hash_map: HashMap<i32, i32> = HashMap::new();
+    let _ = std::mem::take(&mut hash_map);
+
+    let mut btree_map: BTreeMap<i32, i32> = BTreeMap::new();
+    let _ = std::mem::take(&mut btree_map);
+
+    let mut vd: VecDeque<i32> = VecDeque::new();
+    let _ = std::mem::take(&mut vd);
+
+    let mut hash_set: HashSet<&str> = HashSet::new();
+    let _ = std::mem::take(&mut hash_set);
+
+    let mut btree_set: BTreeSet<&str> = BTreeSet::new();
+    let _ = std::mem::take(&mut btree_set);
+
+    let mut list: LinkedList<i32> = LinkedList::new();
+    let _ = std::mem::take(&mut list);
+
+    let mut binary_heap: BinaryHeap<i32> = BinaryHeap::new();
+    let _ = std::mem::take(&mut binary_heap);
 }
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/mem_replace.rs b/src/tools/clippy/tests/ui/mem_replace.rs
index 60f52781071..0a36db9e921 100644
--- a/src/tools/clippy/tests/ui/mem_replace.rs
+++ b/src/tools/clippy/tests/ui/mem_replace.rs
@@ -7,6 +7,7 @@
     clippy::mem_replace_with_default
 )]
 
+use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
 use std::mem;
 
 fn replace_option_with_none() {
@@ -19,9 +20,37 @@ fn replace_option_with_none() {
 fn replace_with_default() {
     let mut s = String::from("foo");
     let _ = std::mem::replace(&mut s, String::default());
+
     let s = &mut String::from("foo");
     let _ = std::mem::replace(s, String::default());
     let _ = std::mem::replace(s, Default::default());
+
+    let mut v = vec![123];
+    let _ = std::mem::replace(&mut v, Vec::default());
+    let _ = std::mem::replace(&mut v, Default::default());
+    let _ = std::mem::replace(&mut v, Vec::new());
+    let _ = std::mem::replace(&mut v, vec![]);
+
+    let mut hash_map: HashMap<i32, i32> = HashMap::new();
+    let _ = std::mem::replace(&mut hash_map, HashMap::new());
+
+    let mut btree_map: BTreeMap<i32, i32> = BTreeMap::new();
+    let _ = std::mem::replace(&mut btree_map, BTreeMap::new());
+
+    let mut vd: VecDeque<i32> = VecDeque::new();
+    let _ = std::mem::replace(&mut vd, VecDeque::new());
+
+    let mut hash_set: HashSet<&str> = HashSet::new();
+    let _ = std::mem::replace(&mut hash_set, HashSet::new());
+
+    let mut btree_set: BTreeSet<&str> = BTreeSet::new();
+    let _ = std::mem::replace(&mut btree_set, BTreeSet::new());
+
+    let mut list: LinkedList<i32> = LinkedList::new();
+    let _ = std::mem::replace(&mut list, LinkedList::new());
+
+    let mut binary_heap: BinaryHeap<i32> = BinaryHeap::new();
+    let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new());
 }
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/mem_replace.stderr b/src/tools/clippy/tests/ui/mem_replace.stderr
index 245d33aa4f2..f8aa1538bff 100644
--- a/src/tools/clippy/tests/ui/mem_replace.stderr
+++ b/src/tools/clippy/tests/ui/mem_replace.stderr
@@ -1,5 +1,5 @@
 error: replacing an `Option` with `None`
-  --> $DIR/mem_replace.rs:14:13
+  --> $DIR/mem_replace.rs:15:13
    |
 LL |     let _ = mem::replace(&mut an_option, None);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()`
@@ -7,13 +7,13 @@ LL |     let _ = mem::replace(&mut an_option, None);
    = note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings`
 
 error: replacing an `Option` with `None`
-  --> $DIR/mem_replace.rs:16:13
+  --> $DIR/mem_replace.rs:17:13
    |
 LL |     let _ = mem::replace(an_option, None);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()`
 
 error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
-  --> $DIR/mem_replace.rs:21:13
+  --> $DIR/mem_replace.rs:22:13
    |
 LL |     let _ = std::mem::replace(&mut s, String::default());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)`
@@ -21,16 +21,82 @@ LL |     let _ = std::mem::replace(&mut s, String::default());
    = note: `-D clippy::mem-replace-with-default` implied by `-D warnings`
 
 error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
-  --> $DIR/mem_replace.rs:23:13
+  --> $DIR/mem_replace.rs:25:13
    |
 LL |     let _ = std::mem::replace(s, String::default());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)`
 
 error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
-  --> $DIR/mem_replace.rs:24:13
+  --> $DIR/mem_replace.rs:26:13
    |
 LL |     let _ = std::mem::replace(s, Default::default());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)`
 
-error: aborting due to 5 previous errors
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:29:13
+   |
+LL |     let _ = std::mem::replace(&mut v, Vec::default());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:30:13
+   |
+LL |     let _ = std::mem::replace(&mut v, Default::default());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:31:13
+   |
+LL |     let _ = std::mem::replace(&mut v, Vec::new());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:32:13
+   |
+LL |     let _ = std::mem::replace(&mut v, vec![]);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:35:13
+   |
+LL |     let _ = std::mem::replace(&mut hash_map, HashMap::new());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_map)`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:38:13
+   |
+LL |     let _ = std::mem::replace(&mut btree_map, BTreeMap::new());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_map)`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:41:13
+   |
+LL |     let _ = std::mem::replace(&mut vd, VecDeque::new());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut vd)`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:44:13
+   |
+LL |     let _ = std::mem::replace(&mut hash_set, HashSet::new());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_set)`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:47:13
+   |
+LL |     let _ = std::mem::replace(&mut btree_set, BTreeSet::new());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_set)`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:50:13
+   |
+LL |     let _ = std::mem::replace(&mut list, LinkedList::new());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut list)`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:53:13
+   |
+LL |     let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut binary_heap)`
+
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_question_mark.fixed b/src/tools/clippy/tests/ui/needless_question_mark.fixed
index 71fb3565224..fd8433870bb 100644
--- a/src/tools/clippy/tests/ui/needless_question_mark.fixed
+++ b/src/tools/clippy/tests/ui/needless_question_mark.fixed
@@ -167,3 +167,28 @@ mod question_mark_both {
         needless_question_mark_result();
     }
 }
+
+// #6921 if a macro wraps an expr in Some(  ) and the ? is in the macro use,
+// the suggestion fails to apply; do not lint
+macro_rules! some_in_macro {
+    ($expr:expr) => {
+        || -> _ { Some($expr) }()
+    };
+}
+
+pub fn test1() {
+    let x = Some(3);
+    let _x = some_in_macro!(x?);
+}
+
+// this one is ok because both the ? and the Some are both inside the macro def
+macro_rules! some_and_qmark_in_macro {
+    ($expr:expr) => {
+        || -> Option<_> { Some($expr) }()
+    };
+}
+
+pub fn test2() {
+    let x = Some(3);
+    let _x = some_and_qmark_in_macro!(x?);
+}
diff --git a/src/tools/clippy/tests/ui/needless_question_mark.rs b/src/tools/clippy/tests/ui/needless_question_mark.rs
index e31f6f48fa7..36d45ac7e03 100644
--- a/src/tools/clippy/tests/ui/needless_question_mark.rs
+++ b/src/tools/clippy/tests/ui/needless_question_mark.rs
@@ -167,3 +167,28 @@ mod question_mark_both {
         needless_question_mark_result();
     }
 }
+
+// #6921 if a macro wraps an expr in Some(  ) and the ? is in the macro use,
+// the suggestion fails to apply; do not lint
+macro_rules! some_in_macro {
+    ($expr:expr) => {
+        || -> _ { Some($expr) }()
+    };
+}
+
+pub fn test1() {
+    let x = Some(3);
+    let _x = some_in_macro!(x?);
+}
+
+// this one is ok because both the ? and the Some are both inside the macro def
+macro_rules! some_and_qmark_in_macro {
+    ($expr:expr) => {
+        || -> Option<_> { Some(Some($expr)?) }()
+    };
+}
+
+pub fn test2() {
+    let x = Some(3);
+    let _x = some_and_qmark_in_macro!(x?);
+}
diff --git a/src/tools/clippy/tests/ui/needless_question_mark.stderr b/src/tools/clippy/tests/ui/needless_question_mark.stderr
index 983c56031d8..7cbf1e505ad 100644
--- a/src/tools/clippy/tests/ui/needless_question_mark.stderr
+++ b/src/tools/clippy/tests/ui/needless_question_mark.stderr
@@ -84,5 +84,16 @@ error: question mark operator is useless here
 LL |         Ok(to.magic?) // should be triggered
    |         ^^^^^^^^^^^^^ help: try: `to.magic`
 
-error: aborting due to 14 previous errors
+error: question mark operator is useless here
+  --> $DIR/needless_question_mark.rs:187:27
+   |
+LL |         || -> Option<_> { Some(Some($expr)?) }()
+   |                           ^^^^^^^^^^^^^^^^^^ help: try: `Some($expr)`
+...
+LL |     let _x = some_and_qmark_in_macro!(x?);
+   |              ---------------------------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 15 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 e82873629a5..2f315ffe298 100644
--- a/src/tools/clippy/tests/ui/new_ret_no_self.rs
+++ b/src/tools/clippy/tests/ui/new_ret_no_self.rs
@@ -340,3 +340,13 @@ mod issue5435 {
         }
     }
 }
+
+// issue #1724
+struct RetOtherSelf<T>(T);
+struct RetOtherSelfWrapper<T>(T);
+
+impl RetOtherSelf<T> {
+    fn new(t: T) -> RetOtherSelf<RetOtherSelfWrapper<T>> {
+        RetOtherSelf(RetOtherSelfWrapper(t))
+    }
+}
diff --git a/src/tools/clippy/tests/ui/new_without_default.rs b/src/tools/clippy/tests/ui/new_without_default.rs
index 3b6041823d8..64659b63f46 100644
--- a/src/tools/clippy/tests/ui/new_without_default.rs
+++ b/src/tools/clippy/tests/ui/new_without_default.rs
@@ -159,4 +159,19 @@ impl NewNotEqualToDerive {
     }
 }
 
+// see #6933
+pub struct FooGenerics<T>(std::marker::PhantomData<T>);
+impl<T> FooGenerics<T> {
+    pub fn new() -> Self {
+        Self(Default::default())
+    }
+}
+
+pub struct BarGenerics<T>(std::marker::PhantomData<T>);
+impl<T: Copy> BarGenerics<T> {
+    pub fn new() -> Self {
+        Self(Default::default())
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/new_without_default.stderr b/src/tools/clippy/tests/ui/new_without_default.stderr
index e529e441eb7..973836f75a9 100644
--- a/src/tools/clippy/tests/ui/new_without_default.stderr
+++ b/src/tools/clippy/tests/ui/new_without_default.stderr
@@ -43,7 +43,7 @@ LL | |     }
    |
 help: try this
    |
-LL | impl Default for LtKo<'c> {
+LL | impl<'c> Default for LtKo<'c> {
 LL |     fn default() -> Self {
 LL |         Self::new()
 LL |     }
@@ -67,5 +67,39 @@ LL |     }
 LL | }
    |
 
-error: aborting due to 4 previous errors
+error: you should consider adding a `Default` implementation for `FooGenerics<T>`
+  --> $DIR/new_without_default.rs:165:5
+   |
+LL | /     pub fn new() -> Self {
+LL | |         Self(Default::default())
+LL | |     }
+   | |_____^
+   |
+help: try this
+   |
+LL | impl<T> Default for FooGenerics<T> {
+LL |     fn default() -> Self {
+LL |         Self::new()
+LL |     }
+LL | }
+   |
+
+error: you should consider adding a `Default` implementation for `BarGenerics<T>`
+  --> $DIR/new_without_default.rs:172:5
+   |
+LL | /     pub fn new() -> Self {
+LL | |         Self(Default::default())
+LL | |     }
+   | |_____^
+   |
+help: try this
+   |
+LL | impl<T: Copy> Default for BarGenerics<T> {
+LL |     fn default() -> Self {
+LL |         Self::new()
+LL |     }
+LL | }
+   |
+
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/or_fun_call.fixed b/src/tools/clippy/tests/ui/or_fun_call.fixed
index 64347cae5da..4390ff7dc30 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.fixed
+++ b/src/tools/clippy/tests/ui/or_fun_call.fixed
@@ -120,6 +120,9 @@ fn test_or_with_ctors() {
 
     let slice = &["foo"][..];
     let _ = opt.ok_or(slice.len());
+
+    let string = "foo";
+    let _ = opt.ok_or(string.len());
 }
 
 // Issue 4514 - early return
@@ -132,4 +135,18 @@ fn f() -> Option<()> {
     Some(())
 }
 
+mod issue6675 {
+    unsafe fn foo() {
+        let mut s = "test".to_owned();
+        None.unwrap_or_else(|| s.as_mut_vec());
+    }
+
+    fn bar() {
+        let mut s = "test".to_owned();
+        None.unwrap_or_else(|| unsafe { s.as_mut_vec() });
+        #[rustfmt::skip]
+        None.unwrap_or_else(|| unsafe { s.as_mut_vec() });
+    }
+}
+
 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 7faab0017b2..75908c974cc 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.rs
+++ b/src/tools/clippy/tests/ui/or_fun_call.rs
@@ -120,6 +120,9 @@ fn test_or_with_ctors() {
 
     let slice = &["foo"][..];
     let _ = opt.ok_or(slice.len());
+
+    let string = "foo";
+    let _ = opt.ok_or(string.len());
 }
 
 // Issue 4514 - early return
@@ -132,4 +135,18 @@ fn f() -> Option<()> {
     Some(())
 }
 
+mod issue6675 {
+    unsafe fn foo() {
+        let mut s = "test".to_owned();
+        None.unwrap_or(s.as_mut_vec());
+    }
+
+    fn bar() {
+        let mut s = "test".to_owned();
+        None.unwrap_or(unsafe { s.as_mut_vec() });
+        #[rustfmt::skip]
+        None.unwrap_or( unsafe { s.as_mut_vec() }    );
+    }
+}
+
 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 1e2bfd490e0..9905029ce91 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.stderr
+++ b/src/tools/clippy/tests/ui/or_fun_call.stderr
@@ -114,5 +114,23 @@ error: use of `or` followed by a function call
 LL |         .or(Some(Bar(b, Duration::from_secs(2))));
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some(Bar(b, Duration::from_secs(2))))`
 
-error: aborting due to 19 previous errors
+error: use of `unwrap_or` followed by a function call
+  --> $DIR/or_fun_call.rs:141:14
+   |
+LL |         None.unwrap_or(s.as_mut_vec());
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| s.as_mut_vec())`
+
+error: use of `unwrap_or` followed by a function call
+  --> $DIR/or_fun_call.rs:146:14
+   |
+LL |         None.unwrap_or(unsafe { s.as_mut_vec() });
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { s.as_mut_vec() })`
+
+error: use of `unwrap_or` followed by a function call
+  --> $DIR/or_fun_call.rs:148:14
+   |
+LL |         None.unwrap_or( unsafe { s.as_mut_vec() }    );
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { s.as_mut_vec() })`
+
+error: aborting due to 22 previous errors
 
diff --git a/src/tools/clippy/tests/ui/print.stderr b/src/tools/clippy/tests/ui/print.stderr
index 208d9532628..1754c418381 100644
--- a/src/tools/clippy/tests/ui/print.stderr
+++ b/src/tools/clippy/tests/ui/print.stderr
@@ -1,8 +1,8 @@
 error: use of `Debug`-based formatting
-  --> $DIR/print.rs:11:19
+  --> $DIR/print.rs:11:20
    |
 LL |         write!(f, "{:?}", 43.1415)
-   |                   ^^^^^^
+   |                    ^^^^
    |
    = note: `-D clippy::use-debug` implied by `-D warnings`
 
@@ -33,10 +33,10 @@ LL |     print!("Hello {:?}", "World");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of `Debug`-based formatting
-  --> $DIR/print.rs:28:12
+  --> $DIR/print.rs:28:19
    |
 LL |     print!("Hello {:?}", "World");
-   |            ^^^^^^^^^^^^
+   |                   ^^^^
 
 error: use of `print!`
   --> $DIR/print.rs:30:5
@@ -45,10 +45,10 @@ LL |     print!("Hello {:#?}", "#orld");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of `Debug`-based formatting
-  --> $DIR/print.rs:30:12
+  --> $DIR/print.rs:30:19
    |
 LL |     print!("Hello {:#?}", "#orld");
-   |            ^^^^^^^^^^^^^
+   |                   ^^^^^
 
 error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/print_literal.stderr b/src/tools/clippy/tests/ui/print_literal.stderr
index e284aece236..54a4084c89e 100644
--- a/src/tools/clippy/tests/ui/print_literal.stderr
+++ b/src/tools/clippy/tests/ui/print_literal.stderr
@@ -5,66 +5,120 @@ LL |     print!("Hello {}", "world");
    |                        ^^^^^^^
    |
    = note: `-D clippy::print-literal` implied by `-D warnings`
+help: try this
+   |
+LL |     print!("Hello world");
+   |                   ^^^^^--
 
 error: literal with an empty format string
   --> $DIR/print_literal.rs:26:36
    |
 LL |     println!("Hello {} {}", world, "world");
    |                                    ^^^^^^^
+   |
+help: try this
+   |
+LL |     println!("Hello {} world", world);
+   |                        ^^^^^       --
 
 error: literal with an empty format string
   --> $DIR/print_literal.rs:27:26
    |
 LL |     println!("Hello {}", "world");
    |                          ^^^^^^^
+   |
+help: try this
+   |
+LL |     println!("Hello world");
+   |                     ^^^^^--
 
 error: literal with an empty format string
   --> $DIR/print_literal.rs:32:25
    |
 LL |     println!("{0} {1}", "hello", "world");
    |                         ^^^^^^^
+   |
+help: try this
+   |
+LL |     println!("hello {1}", "world");
+   |               ^^^^^    --
 
 error: literal with an empty format string
   --> $DIR/print_literal.rs:32:34
    |
 LL |     println!("{0} {1}", "hello", "world");
    |                                  ^^^^^^^
+   |
+help: try this
+   |
+LL |     println!("{0} world", "hello");
+   |                   ^^^^^         --
 
 error: literal with an empty format string
   --> $DIR/print_literal.rs:33:25
    |
 LL |     println!("{1} {0}", "hello", "world");
    |                         ^^^^^^^
+   |
+help: try this
+   |
+LL |     println!("{1} hello", "world");
+   |                   ^^^^^--
 
 error: literal with an empty format string
   --> $DIR/print_literal.rs:33:34
    |
 LL |     println!("{1} {0}", "hello", "world");
    |                                  ^^^^^^^
+   |
+help: try this
+   |
+LL |     println!("world {0}", "hello");
+   |               ^^^^^             --
 
 error: literal with an empty format string
-  --> $DIR/print_literal.rs:36:35
+  --> $DIR/print_literal.rs:36:29
    |
 LL |     println!("{foo} {bar}", foo = "hello", bar = "world");
-   |                                   ^^^^^^^
+   |                             ^^^^^^^^^^^^^
+   |
+help: try this
+   |
+LL |     println!("hello {bar}", bar = "world");
+   |               ^^^^^      --
 
 error: literal with an empty format string
-  --> $DIR/print_literal.rs:36:50
+  --> $DIR/print_literal.rs:36:44
    |
 LL |     println!("{foo} {bar}", foo = "hello", bar = "world");
-   |                                                  ^^^^^^^
+   |                                            ^^^^^^^^^^^^^
+   |
+help: try this
+   |
+LL |     println!("{foo} world", foo = "hello");
+   |                     ^^^^^               --
 
 error: literal with an empty format string
-  --> $DIR/print_literal.rs:37:35
+  --> $DIR/print_literal.rs:37:29
    |
 LL |     println!("{bar} {foo}", foo = "hello", bar = "world");
-   |                                   ^^^^^^^
+   |                             ^^^^^^^^^^^^^
+   |
+help: try this
+   |
+LL |     println!("{bar} hello", bar = "world");
+   |                     ^^^^^--
 
 error: literal with an empty format string
-  --> $DIR/print_literal.rs:37:50
+  --> $DIR/print_literal.rs:37:44
    |
 LL |     println!("{bar} {foo}", foo = "hello", bar = "world");
-   |                                                  ^^^^^^^
+   |                                            ^^^^^^^^^^^^^
+   |
+help: try this
+   |
+LL |     println!("world {foo}", foo = "hello");
+   |               ^^^^^                     --
 
 error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/search_is_some.rs b/src/tools/clippy/tests/ui/search_is_some.rs
index f0dc3b3d06b..72bc6ef35d3 100644
--- a/src/tools/clippy/tests/ui/search_is_some.rs
+++ b/src/tools/clippy/tests/ui/search_is_some.rs
@@ -1,8 +1,9 @@
 // aux-build:option_helpers.rs
+#![warn(clippy::search_is_some)]
+#![allow(dead_code)]
 extern crate option_helpers;
 use option_helpers::IteratorFalsePositives;
 
-#[warn(clippy::search_is_some)]
 #[rustfmt::skip]
 fn main() {
     let v = vec![3, 2, 1, 0, -1, -2, -3];
@@ -36,3 +37,37 @@ fn main() {
     // `Pattern` that is not a string
     let _ = "hello world".find(|c: char| c == 'o' || c == 'l').is_some();
 }
+
+#[rustfmt::skip]
+fn is_none() {
+    let v = vec![3, 2, 1, 0, -1, -2, -3];
+    let y = &&42;
+
+
+    // Check `find().is_none()`, multi-line case.
+    let _ = v.iter().find(|&x| {
+                              *x < 0
+                          }
+                   ).is_none();
+
+    // Check `position().is_none()`, multi-line case.
+    let _ = v.iter().position(|&x| {
+                                  x < 0
+                              }
+                   ).is_none();
+
+    // Check `rposition().is_none()`, multi-line case.
+    let _ = v.iter().rposition(|&x| {
+                                   x < 0
+                               }
+                   ).is_none();
+
+    // Check that we don't lint if the caller is not an `Iterator` or string
+    let falsepos = IteratorFalsePositives { foo: 0 };
+    let _ = falsepos.find().is_none();
+    let _ = falsepos.position().is_none();
+    let _ = falsepos.rposition().is_none();
+    // check that we don't lint if `find()` is called with
+    // `Pattern` that is not a string
+    let _ = "hello world".find(|c: char| c == 'o' || c == 'l').is_none();
+}
diff --git a/src/tools/clippy/tests/ui/search_is_some.stderr b/src/tools/clippy/tests/ui/search_is_some.stderr
index c601f568c60..f3c758e451e 100644
--- a/src/tools/clippy/tests/ui/search_is_some.stderr
+++ b/src/tools/clippy/tests/ui/search_is_some.stderr
@@ -1,5 +1,5 @@
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some.rs:13:13
+  --> $DIR/search_is_some.rs:14:13
    |
 LL |       let _ = v.iter().find(|&x| {
    |  _____________^
@@ -12,7 +12,7 @@ LL | |                    ).is_some();
    = help: this is more succinctly expressed by calling `any()`
 
 error: called `is_some()` after searching an `Iterator` with `position`
-  --> $DIR/search_is_some.rs:19:13
+  --> $DIR/search_is_some.rs:20:13
    |
 LL |       let _ = v.iter().position(|&x| {
    |  _____________^
@@ -24,7 +24,7 @@ LL | |                    ).is_some();
    = help: this is more succinctly expressed by calling `any()`
 
 error: called `is_some()` after searching an `Iterator` with `rposition`
-  --> $DIR/search_is_some.rs:25:13
+  --> $DIR/search_is_some.rs:26:13
    |
 LL |       let _ = v.iter().rposition(|&x| {
    |  _____________^
@@ -35,5 +35,41 @@ LL | |                    ).is_some();
    |
    = help: this is more succinctly expressed by calling `any()`
 
-error: aborting due to 3 previous errors
+error: called `is_none()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some.rs:48:13
+   |
+LL |       let _ = v.iter().find(|&x| {
+   |  _____________^
+LL | |                               *x < 0
+LL | |                           }
+LL | |                    ).is_none();
+   | |______________________________^
+   |
+   = help: this is more succinctly expressed by calling `any()` with negation
+
+error: called `is_none()` after searching an `Iterator` with `position`
+  --> $DIR/search_is_some.rs:54:13
+   |
+LL |       let _ = v.iter().position(|&x| {
+   |  _____________^
+LL | |                                   x < 0
+LL | |                               }
+LL | |                    ).is_none();
+   | |______________________________^
+   |
+   = help: this is more succinctly expressed by calling `any()` with negation
+
+error: called `is_none()` after searching an `Iterator` with `rposition`
+  --> $DIR/search_is_some.rs:60:13
+   |
+LL |       let _ = v.iter().rposition(|&x| {
+   |  _____________^
+LL | |                                    x < 0
+LL | |                                }
+LL | |                    ).is_none();
+   | |______________________________^
+   |
+   = help: this is more succinctly expressed by calling `any()` with negation
+
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable.fixed
index dc3f290e562..62ff16f67f4 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable.fixed
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable.fixed
@@ -1,5 +1,5 @@
 // run-rustfix
-
+#![allow(dead_code)]
 #![warn(clippy::search_is_some)]
 
 fn main() {
@@ -33,3 +33,36 @@ fn main() {
     let _ = s1[2..].contains(&s2);
     let _ = s1[2..].contains(&s2[2..]);
 }
+
+fn is_none() {
+    let v = vec![3, 2, 1, 0, -1, -2, -3];
+    let y = &&42;
+
+    // Check `find().is_none()`, single-line case.
+    let _ = !v.iter().any(|x| *x < 0);
+    let _ = !(0..1).any(|x| **y == x); // one dereference less
+    let _ = !(0..1).any(|x| x == 0);
+    let _ = !v.iter().any(|x| *x == 0);
+
+    // Check `position().is_none()`, single-line case.
+    let _ = !v.iter().any(|&x| x < 0);
+
+    // Check `rposition().is_none()`, single-line case.
+    let _ = !v.iter().any(|&x| x < 0);
+
+    let s1 = String::from("hello world");
+    let s2 = String::from("world");
+
+    // caller of `find()` is a `&`static str`
+    let _ = !"hello world".contains("world");
+    let _ = !"hello world".contains(&s2);
+    let _ = !"hello world".contains(&s2[2..]);
+    // caller of `find()` is a `String`
+    let _ = !s1.contains("world");
+    let _ = !s1.contains(&s2);
+    let _ = !s1.contains(&s2[2..]);
+    // caller of `find()` is slice of `String`
+    let _ = !s1[2..].contains("world");
+    let _ = !s1[2..].contains(&s2);
+    let _ = !s1[2..].contains(&s2[2..]);
+}
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable.rs b/src/tools/clippy/tests/ui/search_is_some_fixable.rs
index 146cf5adf1b..8407f716647 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable.rs
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable.rs
@@ -1,5 +1,5 @@
 // run-rustfix
-
+#![allow(dead_code)]
 #![warn(clippy::search_is_some)]
 
 fn main() {
@@ -33,3 +33,36 @@ fn main() {
     let _ = s1[2..].find(&s2).is_some();
     let _ = s1[2..].find(&s2[2..]).is_some();
 }
+
+fn is_none() {
+    let v = vec![3, 2, 1, 0, -1, -2, -3];
+    let y = &&42;
+
+    // Check `find().is_none()`, single-line case.
+    let _ = v.iter().find(|&x| *x < 0).is_none();
+    let _ = (0..1).find(|x| **y == *x).is_none(); // one dereference less
+    let _ = (0..1).find(|x| *x == 0).is_none();
+    let _ = v.iter().find(|x| **x == 0).is_none();
+
+    // Check `position().is_none()`, single-line case.
+    let _ = v.iter().position(|&x| x < 0).is_none();
+
+    // Check `rposition().is_none()`, single-line case.
+    let _ = v.iter().rposition(|&x| x < 0).is_none();
+
+    let s1 = String::from("hello world");
+    let s2 = String::from("world");
+
+    // caller of `find()` is a `&`static str`
+    let _ = "hello world".find("world").is_none();
+    let _ = "hello world".find(&s2).is_none();
+    let _ = "hello world".find(&s2[2..]).is_none();
+    // caller of `find()` is a `String`
+    let _ = s1.find("world").is_none();
+    let _ = s1.find(&s2).is_none();
+    let _ = s1.find(&s2[2..]).is_none();
+    // caller of `find()` is slice of `String`
+    let _ = s1[2..].find("world").is_none();
+    let _ = s1[2..].find(&s2).is_none();
+    let _ = s1[2..].find(&s2[2..]).is_none();
+}
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable.stderr b/src/tools/clippy/tests/ui/search_is_some_fixable.stderr
index 23c1d9a901b..bd1b6955a97 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable.stderr
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable.stderr
@@ -90,5 +90,95 @@ error: called `is_some()` after calling `find()` on a string
 LL |     let _ = s1[2..].find(&s2[2..]).is_some();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains(&s2[2..])`
 
-error: aborting due to 15 previous errors
+error: called `is_none()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some_fixable.rs:42:13
+   |
+LL |     let _ = v.iter().find(|&x| *x < 0).is_none();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|x| *x < 0)`
+
+error: called `is_none()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some_fixable.rs:43:13
+   |
+LL |     let _ = (0..1).find(|x| **y == *x).is_none(); // one dereference less
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!(0..1).any(|x| **y == x)`
+
+error: called `is_none()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some_fixable.rs:44:13
+   |
+LL |     let _ = (0..1).find(|x| *x == 0).is_none();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!(0..1).any(|x| x == 0)`
+
+error: called `is_none()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some_fixable.rs:45:13
+   |
+LL |     let _ = v.iter().find(|x| **x == 0).is_none();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|x| *x == 0)`
+
+error: called `is_none()` after searching an `Iterator` with `position`
+  --> $DIR/search_is_some_fixable.rs:48:13
+   |
+LL |     let _ = v.iter().position(|&x| x < 0).is_none();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|&x| x < 0)`
+
+error: called `is_none()` after searching an `Iterator` with `rposition`
+  --> $DIR/search_is_some_fixable.rs:51:13
+   |
+LL |     let _ = v.iter().rposition(|&x| x < 0).is_none();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|&x| x < 0)`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:57:13
+   |
+LL |     let _ = "hello world".find("world").is_none();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!"hello world".contains("world")`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:58:13
+   |
+LL |     let _ = "hello world".find(&s2).is_none();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!"hello world".contains(&s2)`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:59:13
+   |
+LL |     let _ = "hello world".find(&s2[2..]).is_none();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!"hello world".contains(&s2[2..])`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:61:13
+   |
+LL |     let _ = s1.find("world").is_none();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1.contains("world")`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:62:13
+   |
+LL |     let _ = s1.find(&s2).is_none();
+   |             ^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1.contains(&s2)`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:63:13
+   |
+LL |     let _ = s1.find(&s2[2..]).is_none();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1.contains(&s2[2..])`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:65:13
+   |
+LL |     let _ = s1[2..].find("world").is_none();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1[2..].contains("world")`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:66:13
+   |
+LL |     let _ = s1[2..].find(&s2).is_none();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1[2..].contains(&s2)`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable.rs:67:13
+   |
+LL |     let _ = s1[2..].find(&s2[2..]).is_none();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1[2..].contains(&s2[2..])`
+
+error: aborting due to 30 previous errors
 
diff --git a/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed b/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed
index ccf8f61c4a9..dd22bfa5c53 100644
--- a/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed
+++ b/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed
@@ -8,10 +8,16 @@ fn str_lit_as_bytes() {
 
     let bs = br###"raw string with 3# plus " ""###;
 
+    let bs = b"lit to string".to_vec();
+    let bs = b"lit to owned".to_vec();
+
     // no warning, because these cannot be written as byte string literals:
     let ubs = "☃".as_bytes();
     let ubs = "hello there! this is a very long string".as_bytes();
 
+    let ubs = "☃".to_string().into_bytes();
+    let ubs = "this is also too long and shouldn't be fixed".to_string().into_bytes();
+
     let strify = stringify!(foobar).as_bytes();
 
     let current_version = env!("CARGO_PKG_VERSION").as_bytes();
diff --git a/src/tools/clippy/tests/ui/string_lit_as_bytes.rs b/src/tools/clippy/tests/ui/string_lit_as_bytes.rs
index 178df08e249..d2a710ed6b8 100644
--- a/src/tools/clippy/tests/ui/string_lit_as_bytes.rs
+++ b/src/tools/clippy/tests/ui/string_lit_as_bytes.rs
@@ -8,10 +8,16 @@ fn str_lit_as_bytes() {
 
     let bs = r###"raw string with 3# plus " ""###.as_bytes();
 
+    let bs = "lit to string".to_string().into_bytes();
+    let bs = "lit to owned".to_owned().into_bytes();
+
     // no warning, because these cannot be written as byte string literals:
     let ubs = "☃".as_bytes();
     let ubs = "hello there! this is a very long string".as_bytes();
 
+    let ubs = "☃".to_string().into_bytes();
+    let ubs = "this is also too long and shouldn't be fixed".to_string().into_bytes();
+
     let strify = stringify!(foobar).as_bytes();
 
     let current_version = env!("CARGO_PKG_VERSION").as_bytes();
diff --git a/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr b/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr
index 99c512354d5..e0ddb070b50 100644
--- a/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr
+++ b/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr
@@ -12,17 +12,29 @@ error: calling `as_bytes()` on a string literal
 LL |     let bs = r###"raw string with 3# plus " ""###.as_bytes();
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `br###"raw string with 3# plus " ""###`
 
+error: calling `into_bytes()` on a string literal
+  --> $DIR/string_lit_as_bytes.rs:11:14
+   |
+LL |     let bs = "lit to string".to_string().into_bytes();
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"lit to string".to_vec()`
+
+error: calling `into_bytes()` on a string literal
+  --> $DIR/string_lit_as_bytes.rs:12:14
+   |
+LL |     let bs = "lit to owned".to_owned().into_bytes();
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"lit to owned".to_vec()`
+
 error: calling `as_bytes()` on `include_str!(..)`
-  --> $DIR/string_lit_as_bytes.rs:19:22
+  --> $DIR/string_lit_as_bytes.rs:25:22
    |
 LL |     let includestr = include_str!("entry_unfixable.rs").as_bytes();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("entry_unfixable.rs")`
 
 error: calling `as_bytes()` on a string literal
-  --> $DIR/string_lit_as_bytes.rs:21:13
+  --> $DIR/string_lit_as_bytes.rs:27:13
    |
 LL |     let _ = "string with newline/t/n".as_bytes();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"string with newline/t/n"`
 
-error: aborting due to 4 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/suspicious_map.rs b/src/tools/clippy/tests/ui/suspicious_map.rs
index d838d8fde21..3a2a10cf09e 100644
--- a/src/tools/clippy/tests/ui/suspicious_map.rs
+++ b/src/tools/clippy/tests/ui/suspicious_map.rs
@@ -2,4 +2,31 @@
 
 fn main() {
     let _ = (0..3).map(|x| x + 2).count();
+
+    let f = |x| x + 1;
+    let _ = (0..3).map(f).count();
+}
+
+fn negative() {
+    // closure with side effects
+    let mut sum = 0;
+    let _ = (0..3).map(|x| sum += x).count();
+
+    // closure variable with side effects
+    let ext_closure = |x| sum += x;
+    let _ = (0..3).map(ext_closure).count();
+
+    // closure that returns unit
+    let _ = (0..3)
+        .map(|x| {
+            // do nothing
+        })
+        .count();
+
+    // external function
+    let _ = (0..3).map(do_something).count();
+}
+
+fn do_something<T>(t: T) -> String {
+    unimplemented!()
 }
diff --git a/src/tools/clippy/tests/ui/suspicious_map.stderr b/src/tools/clippy/tests/ui/suspicious_map.stderr
index e1b4ba40376..8c3f36584a5 100644
--- a/src/tools/clippy/tests/ui/suspicious_map.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_map.stderr
@@ -7,5 +7,13 @@ LL |     let _ = (0..3).map(|x| x + 2).count();
    = note: `-D clippy::suspicious-map` implied by `-D warnings`
    = help: make sure you did not confuse `map` with `filter` or `for_each`
 
-error: aborting due to previous error
+error: this call to `map()` won't have an effect on the call to `count()`
+  --> $DIR/suspicious_map.rs:7:13
+   |
+LL |     let _ = (0..3).map(f).count();
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: make sure you did not confuse `map` with `filter` or `for_each`
+
+error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.stderr b/src/tools/clippy/tests/ui/unnecessary_cast.stderr
index 8981d13e8ea..70aa448af68 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.stderr
@@ -1,22 +1,22 @@
-error: casting to the same type is unnecessary (`i32` -> `i32`)
+error: casting integer literal to `i32` is unnecessary
   --> $DIR/unnecessary_cast.rs:6:5
    |
 LL |     1i32 as i32;
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ help: try: `1_i32`
    |
    = note: `-D clippy::unnecessary-cast` implied by `-D warnings`
 
-error: casting to the same type is unnecessary (`f32` -> `f32`)
+error: casting float literal to `f32` is unnecessary
   --> $DIR/unnecessary_cast.rs:7:5
    |
 LL |     1f32 as f32;
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ help: try: `1_f32`
 
 error: casting to the same type is unnecessary (`bool` -> `bool`)
   --> $DIR/unnecessary_cast.rs:8:5
    |
 LL |     false as bool;
-   |     ^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^ help: try: `false`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/upper_case_acronyms.rs b/src/tools/clippy/tests/ui/upper_case_acronyms.rs
index 735909887ac..8c09c6f5b23 100644
--- a/src/tools/clippy/tests/ui/upper_case_acronyms.rs
+++ b/src/tools/clippy/tests/ui/upper_case_acronyms.rs
@@ -20,4 +20,8 @@ enum Flags {
 // `GccLlvmSomething`
 struct GCCLLVMSomething;
 
+// public items must not be linted
+pub struct NOWARNINGHERE;
+pub struct ALSONoWarningHERE;
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/use_self.fixed b/src/tools/clippy/tests/ui/use_self.fixed
index b94d5448d92..1282befdfb3 100644
--- a/src/tools/clippy/tests/ui/use_self.fixed
+++ b/src/tools/clippy/tests/ui/use_self.fixed
@@ -75,13 +75,13 @@ mod lifetimes {
 
 mod issue2894 {
     trait IntoBytes {
-        fn to_bytes(&self) -> Vec<u8>;
+        fn to_bytes(self) -> Vec<u8>;
     }
 
     // This should not be linted
     impl IntoBytes for u8 {
-        fn to_bytes(&self) -> Vec<u8> {
-            vec![*self]
+        fn to_bytes(self) -> Vec<u8> {
+            vec![self]
         }
     }
 }
diff --git a/src/tools/clippy/tests/ui/use_self.rs b/src/tools/clippy/tests/ui/use_self.rs
index ac99c6d9d7b..7aaac7b2414 100644
--- a/src/tools/clippy/tests/ui/use_self.rs
+++ b/src/tools/clippy/tests/ui/use_self.rs
@@ -75,13 +75,13 @@ mod lifetimes {
 
 mod issue2894 {
     trait IntoBytes {
-        fn to_bytes(&self) -> Vec<u8>;
+        fn to_bytes(self) -> Vec<u8>;
     }
 
     // This should not be linted
     impl IntoBytes for u8 {
-        fn to_bytes(&self) -> Vec<u8> {
-            vec![*self]
+        fn to_bytes(self) -> Vec<u8> {
+            vec![self]
         }
     }
 }
diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
index c266f684a36..fd754e4c794 100644
--- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
+++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
@@ -77,7 +77,7 @@ fn main() {
     let error_kind = ErrorKind::NotFound;
     match error_kind {
         ErrorKind::NotFound => {},
-        std::io::ErrorKind::PermissionDenied | std::io::ErrorKind::ConnectionRefused | std::io::ErrorKind::ConnectionReset | std::io::ErrorKind::ConnectionAborted | std::io::ErrorKind::NotConnected | std::io::ErrorKind::AddrInUse | std::io::ErrorKind::AddrNotAvailable | std::io::ErrorKind::BrokenPipe | std::io::ErrorKind::AlreadyExists | std::io::ErrorKind::WouldBlock | std::io::ErrorKind::InvalidInput | std::io::ErrorKind::InvalidData | std::io::ErrorKind::TimedOut | std::io::ErrorKind::WriteZero | std::io::ErrorKind::Interrupted | std::io::ErrorKind::Other | std::io::ErrorKind::UnexpectedEof | _ => {},
+        ErrorKind::PermissionDenied | ErrorKind::ConnectionRefused | ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::NotConnected | ErrorKind::AddrInUse | ErrorKind::AddrNotAvailable | ErrorKind::BrokenPipe | ErrorKind::AlreadyExists | ErrorKind::WouldBlock | ErrorKind::InvalidInput | ErrorKind::InvalidData | ErrorKind::TimedOut | ErrorKind::WriteZero | ErrorKind::Interrupted | ErrorKind::Other | ErrorKind::UnexpectedEof | _ => {},
     }
     match error_kind {
         ErrorKind::NotFound => {},
diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr
index 0da2b68ba0b..a513a62c748 100644
--- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr
+++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr
@@ -1,4 +1,4 @@
-error: wildcard match will miss any future added variants
+error: wildcard match will also match any future added variants
   --> $DIR/wildcard_enum_match_arm.rs:39:9
    |
 LL |         _ => eprintln!("Not red"),
@@ -10,29 +10,29 @@ note: the lint level is defined here
 LL | #![deny(clippy::wildcard_enum_match_arm)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: wildcard match will miss any future added variants
+error: wildcard match will also match any future added variants
   --> $DIR/wildcard_enum_match_arm.rs:43:9
    |
 LL |         _not_red => eprintln!("Not red"),
    |         ^^^^^^^^ help: try this: `_not_red @ Color::Green | _not_red @ Color::Blue | _not_red @ Color::Rgb(..) | _not_red @ Color::Cyan`
 
-error: wildcard match will miss any future added variants
+error: wildcard match will also match any future added variants
   --> $DIR/wildcard_enum_match_arm.rs:47:9
    |
 LL |         not_red => format!("{:?}", not_red),
    |         ^^^^^^^ help: try this: `not_red @ Color::Green | not_red @ Color::Blue | not_red @ Color::Rgb(..) | not_red @ Color::Cyan`
 
-error: wildcard match will miss any future added variants
+error: wildcard match will also match any future added variants
   --> $DIR/wildcard_enum_match_arm.rs:63:9
    |
 LL |         _ => "No red",
    |         ^ help: try this: `Color::Red | Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan`
 
-error: match on non-exhaustive enum doesn't explicitly match all known variants
+error: wildcard matches known variants and will also match future added variants
   --> $DIR/wildcard_enum_match_arm.rs:80:9
    |
 LL |         _ => {},
-   |         ^ help: try this: `std::io::ErrorKind::PermissionDenied | std::io::ErrorKind::ConnectionRefused | std::io::ErrorKind::ConnectionReset | std::io::ErrorKind::ConnectionAborted | std::io::ErrorKind::NotConnected | std::io::ErrorKind::AddrInUse | std::io::ErrorKind::AddrNotAvailable | std::io::ErrorKind::BrokenPipe | std::io::ErrorKind::AlreadyExists | std::io::ErrorKind::WouldBlock | std::io::ErrorKind::InvalidInput | std::io::ErrorKind::InvalidData | std::io::ErrorKind::TimedOut | std::io::ErrorKind::WriteZero | std::io::ErrorKind::Interrupted | std::io::ErrorKind::Other | std::io::ErrorKind::UnexpectedEof | _`
+   |         ^ help: try this: `ErrorKind::PermissionDenied | ErrorKind::ConnectionRefused | ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::NotConnected | ErrorKind::AddrInUse | ErrorKind::AddrNotAvailable | ErrorKind::BrokenPipe | ErrorKind::AlreadyExists | ErrorKind::WouldBlock | ErrorKind::InvalidInput | ErrorKind::InvalidData | ErrorKind::TimedOut | ErrorKind::WriteZero | ErrorKind::Interrupted | ErrorKind::Other | ErrorKind::UnexpectedEof | _`
 
 error: aborting due to 5 previous errors
 
diff --git a/src/tools/clippy/tests/ui/write_literal.stderr b/src/tools/clippy/tests/ui/write_literal.stderr
index e54d89ecf29..507a78e8280 100644
--- a/src/tools/clippy/tests/ui/write_literal.stderr
+++ b/src/tools/clippy/tests/ui/write_literal.stderr
@@ -5,66 +5,120 @@ LL |     write!(&mut v, "Hello {}", "world");
    |                                ^^^^^^^
    |
    = note: `-D clippy::write-literal` implied by `-D warnings`
+help: try this
+   |
+LL |     write!(&mut v, "Hello world");
+   |                           ^^^^^--
 
 error: literal with an empty format string
   --> $DIR/write_literal.rs:31:44
    |
 LL |     writeln!(&mut v, "Hello {} {}", world, "world");
    |                                            ^^^^^^^
+   |
+help: try this
+   |
+LL |     writeln!(&mut v, "Hello {} world", world);
+   |                                ^^^^^       --
 
 error: literal with an empty format string
   --> $DIR/write_literal.rs:32:34
    |
 LL |     writeln!(&mut v, "Hello {}", "world");
    |                                  ^^^^^^^
+   |
+help: try this
+   |
+LL |     writeln!(&mut v, "Hello world");
+   |                             ^^^^^--
 
 error: literal with an empty format string
   --> $DIR/write_literal.rs:37:33
    |
 LL |     writeln!(&mut v, "{0} {1}", "hello", "world");
    |                                 ^^^^^^^
+   |
+help: try this
+   |
+LL |     writeln!(&mut v, "hello {1}", "world");
+   |                       ^^^^^    --
 
 error: literal with an empty format string
   --> $DIR/write_literal.rs:37:42
    |
 LL |     writeln!(&mut v, "{0} {1}", "hello", "world");
    |                                          ^^^^^^^
+   |
+help: try this
+   |
+LL |     writeln!(&mut v, "{0} world", "hello");
+   |                           ^^^^^         --
 
 error: literal with an empty format string
   --> $DIR/write_literal.rs:38:33
    |
 LL |     writeln!(&mut v, "{1} {0}", "hello", "world");
    |                                 ^^^^^^^
+   |
+help: try this
+   |
+LL |     writeln!(&mut v, "{1} hello", "world");
+   |                           ^^^^^--
 
 error: literal with an empty format string
   --> $DIR/write_literal.rs:38:42
    |
 LL |     writeln!(&mut v, "{1} {0}", "hello", "world");
    |                                          ^^^^^^^
+   |
+help: try this
+   |
+LL |     writeln!(&mut v, "world {0}", "hello");
+   |                       ^^^^^             --
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:41:43
+  --> $DIR/write_literal.rs:41:37
    |
 LL |     writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world");
-   |                                           ^^^^^^^
+   |                                     ^^^^^^^^^^^^^
+   |
+help: try this
+   |
+LL |     writeln!(&mut v, "hello {bar}", bar = "world");
+   |                       ^^^^^      --
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:41:58
+  --> $DIR/write_literal.rs:41:52
    |
 LL |     writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world");
-   |                                                          ^^^^^^^
+   |                                                    ^^^^^^^^^^^^^
+   |
+help: try this
+   |
+LL |     writeln!(&mut v, "{foo} world", foo = "hello");
+   |                             ^^^^^               --
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:42:43
+  --> $DIR/write_literal.rs:42:37
    |
 LL |     writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world");
-   |                                           ^^^^^^^
+   |                                     ^^^^^^^^^^^^^
+   |
+help: try this
+   |
+LL |     writeln!(&mut v, "{bar} hello", bar = "world");
+   |                             ^^^^^--
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:42:58
+  --> $DIR/write_literal.rs:42:52
    |
 LL |     writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world");
-   |                                                          ^^^^^^^
+   |                                                    ^^^^^^^^^^^^^
+   |
+help: try this
+   |
+LL |     writeln!(&mut v, "world {foo}", foo = "hello");
+   |                       ^^^^^                     --
 
 error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/write_literal_2.rs b/src/tools/clippy/tests/ui/write_literal_2.rs
new file mode 100644
index 00000000000..f341e8215e1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/write_literal_2.rs
@@ -0,0 +1,27 @@
+#![allow(unused_must_use)]
+#![warn(clippy::write_literal)]
+
+use std::io::Write;
+
+fn main() {
+    let mut v = Vec::new();
+
+    writeln!(&mut v, "{}", "{hello}");
+    writeln!(&mut v, r"{}", r"{hello}");
+    writeln!(&mut v, "{}", '\'');
+    writeln!(&mut v, "{}", '"');
+    writeln!(&mut v, r"{}", '"'); // don't lint
+    writeln!(&mut v, r"{}", '\'');
+    writeln!(
+        &mut v,
+        "some {}",
+        "hello \
+        world!"
+    );
+    writeln!(
+        &mut v,
+        "some {}\
+        {} \\ {}",
+        "1", "2", "3",
+    );
+}
diff --git a/src/tools/clippy/tests/ui/write_literal_2.stderr b/src/tools/clippy/tests/ui/write_literal_2.stderr
new file mode 100644
index 00000000000..0aa1b55e58c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/write_literal_2.stderr
@@ -0,0 +1,107 @@
+error: literal with an empty format string
+  --> $DIR/write_literal_2.rs:9:28
+   |
+LL |     writeln!(&mut v, "{}", "{hello}");
+   |                            ^^^^^^^^^
+   |
+   = note: `-D clippy::write-literal` implied by `-D warnings`
+help: try this
+   |
+LL |     writeln!(&mut v, "{{hello}}");
+   |                       ^^^^^^^^^--
+
+error: literal with an empty format string
+  --> $DIR/write_literal_2.rs:10:29
+   |
+LL |     writeln!(&mut v, r"{}", r"{hello}");
+   |                             ^^^^^^^^^^
+   |
+help: try this
+   |
+LL |     writeln!(&mut v, r"{{hello}}");
+   |                        ^^^^^^^^^--
+
+error: literal with an empty format string
+  --> $DIR/write_literal_2.rs:11:28
+   |
+LL |     writeln!(&mut v, "{}", '/'');
+   |                            ^^^^
+   |
+help: try this
+   |
+LL |     writeln!(&mut v, "'");
+   |                       ^--
+
+error: literal with an empty format string
+  --> $DIR/write_literal_2.rs:12:28
+   |
+LL |     writeln!(&mut v, "{}", '"');
+   |                            ^^^
+   |
+help: try this
+   |
+LL |     writeln!(&mut v, "/"");
+   |                       ^^--
+
+error: literal with an empty format string
+  --> $DIR/write_literal_2.rs:14:29
+   |
+LL |     writeln!(&mut v, r"{}", '/'');
+   |                             ^^^^
+   |
+help: try this
+   |
+LL |     writeln!(&mut v, r"'");
+   |                        ^--
+
+error: literal with an empty format string
+  --> $DIR/write_literal_2.rs:18:9
+   |
+LL | /         "hello /
+LL | |         world!"
+   | |_______________^
+   |
+help: try this
+   |
+LL |         "some hello /
+LL |         world!"
+   |
+
+error: literal with an empty format string
+  --> $DIR/write_literal_2.rs:25:9
+   |
+LL |         "1", "2", "3",
+   |         ^^^
+   |
+help: try this
+   |
+LL |         "some 1/
+LL |         {} / {}", "2", "3",
+   |
+
+error: literal with an empty format string
+  --> $DIR/write_literal_2.rs:25:14
+   |
+LL |         "1", "2", "3",
+   |              ^^^
+   |
+help: try this
+   |
+LL |         2 / {}",
+LL |         "1", "3",
+   |
+
+error: literal with an empty format string
+  --> $DIR/write_literal_2.rs:25:19
+   |
+LL |         "1", "2", "3",
+   |                   ^^^
+   |
+help: try this
+   |
+LL |         {} / 3",
+LL |         "1", "2",
+   |
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui/wrong_self_convention.rs b/src/tools/clippy/tests/ui/wrong_self_convention.rs
index 6cfc0fcb4ca..ba9e19a1722 100644
--- a/src/tools/clippy/tests/ui/wrong_self_convention.rs
+++ b/src/tools/clippy/tests/ui/wrong_self_convention.rs
@@ -163,3 +163,35 @@ mod issue6307 {
         fn to_mut(&mut self);
     }
 }
+
+mod issue6727 {
+    trait ToU64 {
+        fn to_u64(self) -> u64;
+        fn to_u64_v2(&self) -> u64;
+    }
+
+    #[derive(Clone, Copy)]
+    struct FooCopy;
+
+    impl ToU64 for FooCopy {
+        fn to_u64(self) -> u64 {
+            1
+        }
+        // trigger lint
+        fn to_u64_v2(&self) -> u64 {
+            1
+        }
+    }
+
+    struct FooNoCopy;
+
+    impl ToU64 for FooNoCopy {
+        // trigger lint
+        fn to_u64(self) -> u64 {
+            2
+        }
+        fn to_u64_v2(&self) -> u64 {
+            2
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/wrong_self_convention.stderr b/src/tools/clippy/tests/ui/wrong_self_convention.stderr
index 32bd9075bd5..1d58a12ac79 100644
--- a/src/tools/clippy/tests/ui/wrong_self_convention.stderr
+++ b/src/tools/clippy/tests/ui/wrong_self_convention.stderr
@@ -1,148 +1,195 @@
-error: methods called `from_*` usually take no self; consider choosing a less ambiguous name
+error: methods called `from_*` usually take no `self`
   --> $DIR/wrong_self_convention.rs:18:17
    |
 LL |     fn from_i32(self) {}
    |                 ^^^^
    |
    = note: `-D clippy::wrong-self-convention` implied by `-D warnings`
+   = help: consider choosing a less ambiguous name
 
-error: methods called `from_*` usually take no self; consider choosing a less ambiguous name
+error: methods called `from_*` usually take no `self`
   --> $DIR/wrong_self_convention.rs:24:21
    |
 LL |     pub fn from_i64(self) {}
    |                     ^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name
+error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
   --> $DIR/wrong_self_convention.rs:36:15
    |
 LL |     fn as_i32(self) {}
    |               ^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name
+error: methods called `into_*` usually take `self` by value
   --> $DIR/wrong_self_convention.rs:38:17
    |
 LL |     fn into_i32(&self) {}
    |                 ^^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name
+error: methods called `is_*` usually take `self` by reference or no `self`
   --> $DIR/wrong_self_convention.rs:40:15
    |
 LL |     fn is_i32(self) {}
    |               ^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name
+error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
   --> $DIR/wrong_self_convention.rs:42:15
    |
 LL |     fn to_i32(self) {}
    |               ^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `from_*` usually take no self; consider choosing a less ambiguous name
+error: methods called `from_*` usually take no `self`
   --> $DIR/wrong_self_convention.rs:44:17
    |
 LL |     fn from_i32(self) {}
    |                 ^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name
+error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
   --> $DIR/wrong_self_convention.rs:46:19
    |
 LL |     pub fn as_i64(self) {}
    |                   ^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name
+error: methods called `into_*` usually take `self` by value
   --> $DIR/wrong_self_convention.rs:47:21
    |
 LL |     pub fn into_i64(&self) {}
    |                     ^^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name
+error: methods called `is_*` usually take `self` by reference or no `self`
   --> $DIR/wrong_self_convention.rs:48:19
    |
 LL |     pub fn is_i64(self) {}
    |                   ^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name
+error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
   --> $DIR/wrong_self_convention.rs:49:19
    |
 LL |     pub fn to_i64(self) {}
    |                   ^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `from_*` usually take no self; consider choosing a less ambiguous name
+error: methods called `from_*` usually take no `self`
   --> $DIR/wrong_self_convention.rs:50:21
    |
 LL |     pub fn from_i64(self) {}
    |                     ^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name
+error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
   --> $DIR/wrong_self_convention.rs:95:19
    |
 LL |         fn as_i32(self) {}
    |                   ^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name
+error: methods called `into_*` usually take `self` by value
   --> $DIR/wrong_self_convention.rs:98:25
    |
 LL |         fn into_i32_ref(&self) {}
    |                         ^^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name
+error: methods called `is_*` usually take `self` by reference or no `self`
   --> $DIR/wrong_self_convention.rs:100:19
    |
 LL |         fn is_i32(self) {}
    |                   ^^^^
-
-error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name
-  --> $DIR/wrong_self_convention.rs:102:19
    |
-LL |         fn to_i32(self) {}
-   |                   ^^^^
+   = help: consider choosing a less ambiguous name
 
-error: methods called `from_*` usually take no self; consider choosing a less ambiguous name
+error: methods called `from_*` usually take no `self`
   --> $DIR/wrong_self_convention.rs:104:21
    |
 LL |         fn from_i32(self) {}
    |                     ^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name
+error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
   --> $DIR/wrong_self_convention.rs:119:19
    |
 LL |         fn as_i32(self);
    |                   ^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name
+error: methods called `into_*` usually take `self` by value
   --> $DIR/wrong_self_convention.rs:122:25
    |
 LL |         fn into_i32_ref(&self);
    |                         ^^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name
+error: methods called `is_*` usually take `self` by reference or no `self`
   --> $DIR/wrong_self_convention.rs:124:19
    |
 LL |         fn is_i32(self);
    |                   ^^^^
-
-error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name
-  --> $DIR/wrong_self_convention.rs:126:19
    |
-LL |         fn to_i32(self);
-   |                   ^^^^
+   = help: consider choosing a less ambiguous name
 
-error: methods called `from_*` usually take no self; consider choosing a less ambiguous name
+error: methods called `from_*` usually take no `self`
   --> $DIR/wrong_self_convention.rs:128:21
    |
 LL |         fn from_i32(self);
    |                     ^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name
+error: methods called `into_*` usually take `self` by value
   --> $DIR/wrong_self_convention.rs:146:25
    |
 LL |         fn into_i32_ref(&self);
    |                         ^^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
-error: methods called `from_*` usually take no self; consider choosing a less ambiguous name
+error: methods called `from_*` usually take no `self`
   --> $DIR/wrong_self_convention.rs:152:21
    |
 LL |         fn from_i32(self);
    |                     ^^^^
+   |
+   = help: consider choosing a less ambiguous name
+
+error: methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value
+  --> $DIR/wrong_self_convention.rs:181:22
+   |
+LL |         fn to_u64_v2(&self) -> u64 {
+   |                      ^^^^^
+   |
+   = help: consider choosing a less ambiguous name
+
+error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
+  --> $DIR/wrong_self_convention.rs:190:19
+   |
+LL |         fn to_u64(self) -> u64 {
+   |                   ^^^^
+   |
+   = help: consider choosing a less ambiguous name
 
 error: aborting due to 24 previous errors
 
diff --git a/src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs
new file mode 100644
index 00000000000..486a0d77235
--- /dev/null
+++ b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs
@@ -0,0 +1,30 @@
+// edition:2018
+#![warn(clippy::wrong_self_convention)]
+#![allow(dead_code)]
+
+fn main() {}
+
+mod issue6758 {
+    pub enum Test<T> {
+        One(T),
+        Many(Vec<T>),
+    }
+
+    impl<T> Test<T> {
+        // If a method starts with `to_` and not ends with `_mut` it should expect `&self`
+        pub fn to_many(&mut self) -> Option<&mut [T]> {
+            match self {
+                Self::Many(data) => Some(data),
+                _ => None,
+            }
+        }
+
+        // If a method starts with `to_` and ends with `_mut` it should expect `&mut self`
+        pub fn to_many_mut(&self) -> Option<&[T]> {
+            match self {
+                Self::Many(data) => Some(data),
+                _ => None,
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr
new file mode 100644
index 00000000000..6ce37c59491
--- /dev/null
+++ b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr
@@ -0,0 +1,19 @@
+error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
+  --> $DIR/wrong_self_conventions_mut.rs:15:24
+   |
+LL |         pub fn to_many(&mut self) -> Option<&mut [T]> {
+   |                        ^^^^^^^^^
+   |
+   = note: `-D clippy::wrong-self-convention` implied by `-D warnings`
+   = help: consider choosing a less ambiguous name
+
+error: methods with the following characteristics: (`to_*` and `*_mut`) usually take `self` by mutable reference
+  --> $DIR/wrong_self_conventions_mut.rs:23:28
+   |
+LL |         pub fn to_many_mut(&self) -> Option<&[T]> {
+   |                            ^^^^^
+   |
+   = help: consider choosing a less ambiguous name
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index ff0d845be93..83ea676e8f4 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -973,7 +973,11 @@ fn parse_normalization_string(line: &mut &str) -> Option<String> {
 }
 
 pub fn extract_llvm_version(version: &str) -> Option<u32> {
-    let version_without_suffix = version.trim_end_matches("git").split('-').next().unwrap();
+    let pat = |c: char| !c.is_ascii_digit() && c != '.';
+    let version_without_suffix = match version.find(pat) {
+        Some(pos) => &version[..pos],
+        None => version,
+    };
     let components: Vec<u32> = version_without_suffix
         .split('.')
         .map(|s| s.parse().expect("Malformed version component"))
diff --git a/src/tools/compiletest/src/tests.rs b/src/tools/compiletest/src/tests.rs
index ea9bc1c1a5b..233f2e648dc 100644
--- a/src/tools/compiletest/src/tests.rs
+++ b/src/tools/compiletest/src/tests.rs
@@ -68,4 +68,8 @@ fn test_extract_llvm_version() {
     assert_eq!(extract_llvm_version("9.0.1-rust-1.43.0-dev"), Some(90001));
     assert_eq!(extract_llvm_version("9.3.1-rust-1.43.0-dev"), Some(90301));
     assert_eq!(extract_llvm_version("10.0.0-rust"), Some(100000));
+    assert_eq!(extract_llvm_version("11.1.0"), Some(110100));
+    assert_eq!(extract_llvm_version("12.0.0libcxx"), Some(120000));
+    assert_eq!(extract_llvm_version("12.0.0-rc3"), Some(120000));
+    assert_eq!(extract_llvm_version("13.0.0git"), Some(130000));
 }
diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml
index 97052ef58d6..a6efc4c9a6b 100644
--- a/src/tools/jsondocck/Cargo.toml
+++ b/src/tools/jsondocck/Cargo.toml
@@ -12,3 +12,4 @@ lazy_static = "1.4"
 shlex = "0.1"
 serde = "1.0"
 serde_json = "1.0"
+fs-err = "2.5.0"
diff --git a/src/tools/jsondocck/src/cache.rs b/src/tools/jsondocck/src/cache.rs
index 8a6a911321c..a188750c56a 100644
--- a/src/tools/jsondocck/src/cache.rs
+++ b/src/tools/jsondocck/src/cache.rs
@@ -1,8 +1,10 @@
 use crate::error::CkError;
 use serde_json::Value;
 use std::collections::HashMap;
+use std::io;
 use std::path::{Path, PathBuf};
-use std::{fs, io};
+
+use fs_err as fs;
 
 #[derive(Debug)]
 pub struct Cache {
@@ -31,7 +33,11 @@ impl Cache {
             self.last_path = Some(resolve.clone());
             resolve
         } else {
-            self.last_path.as_ref().unwrap().clone()
+            self.last_path
+                .as_ref()
+                // FIXME: Point to a line number
+                .expect("No last path set. Make sure to specify a full path before using `-`")
+                .clone()
         }
     }
 
diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs
index bcb3f6922ef..216890d59ad 100644
--- a/src/tools/jsondocck/src/main.rs
+++ b/src/tools/jsondocck/src/main.rs
@@ -239,7 +239,20 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
             let val = cache.get_value(&command.args[0])?;
             let results = select(&val, &command.args[1]).unwrap();
             let pat = string_to_value(&command.args[2], cache);
-            results.len() == 1 && results[0] == pat.as_ref()
+            let is = results.len() == 1 && results[0] == pat.as_ref();
+            if !command.negated && !is {
+                return Err(CkError::FailedCheck(
+                    format!(
+                        "{} matched to {:?}, but expected {:?}",
+                        &command.args[1],
+                        results,
+                        pat.as_ref()
+                    ),
+                    command,
+                ));
+            } else {
+                is
+            }
         }
         CommandKind::Set => {
             // @set <name> = <path> <jsonpath>
@@ -299,7 +312,10 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
 
 fn string_to_value<'a>(s: &str, cache: &'a Cache) -> Cow<'a, Value> {
     if s.starts_with("$") {
-        Cow::Borrowed(&cache.variables[&s[1..]])
+        Cow::Borrowed(&cache.variables.get(&s[1..]).unwrap_or_else(|| {
+            // FIXME(adotinthevoid): Show line number
+            panic!("No variable: `{}`. Current state: `{:?}`", &s[1..], cache.variables)
+        }))
     } else {
         Cow::Owned(serde_json::from_str(s).unwrap())
     }
diff --git a/src/tools/miri b/src/tools/miri
-Subproject 12dac5c0f7acd106401aa14fec758f0ff552f67
+Subproject 2cdd1744b896e8129322229f253f95fd7ad491f
diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
-Subproject 858ad554374a8b1ad67692558a0878391abfdd8
+Subproject bb1d925dab36372c6bd1fb5671bb68ce938ff00
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 96a02038638..51f48d8f2ec 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -32,7 +32,6 @@ const EXCEPTIONS: &[(&str, &str)] = &[
     ("fuchsia-zircon", "BSD-3-Clause"), // rustdoc, rustc, cargo (jobserver & tempdir)
     ("colored", "MPL-2.0"),             // rustfmt
     ("ordslice", "Apache-2.0"),         // rls
-    ("cloudabi", "BSD-2-Clause"),       // (rls -> crossbeam-channel 0.2 -> rand 0.5)
     ("ryu", "Apache-2.0 OR BSL-1.0"),   // rls/cargo/... (because of serde)
     ("bytesize", "Apache-2.0"),         // cargo
     ("im-rc", "MPL-2.0+"),              // cargo
@@ -76,7 +75,6 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
     "cfg-if",
     "chalk-derive",
     "chalk-ir",
-    "cloudabi",
     "cmake",
     "compiler_builtins",
     "cpuid-bool",