about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock16
-rw-r--r--compiler/rustc_ast/README.md3
-rw-r--r--compiler/rustc_ast/src/lib.rs4
-rw-r--r--compiler/rustc_ast/src/util/unicode.rs35
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs49
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs102
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/statement.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs25
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs22
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/resolver.rs18
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs39
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs94
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs21
-rw-r--r--compiler/rustc_lint/src/context.rs4
-rw-r--r--compiler/rustc_lint/src/hidden_unicode_codepoints.rs12
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs1
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp4
-rw-r--r--compiler/rustc_metadata/src/locator.rs4
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs4
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs7
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs132
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/mod.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/rustc_peek.rs31
-rw-r--r--compiler/rustc_monomorphize/src/util.rs2
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs9
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs4
-rw-r--r--compiler/rustc_resolve/src/lib.rs28
-rw-r--r--compiler/rustc_save_analysis/src/dump_visitor.rs4
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs6
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_darwin.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs86
-rw-r--r--compiler/rustc_typeck/src/astconv/generics.rs2
-rw-r--r--compiler/rustc_typeck/src/check/regionck.rs2
-rw-r--r--compiler/rustc_typeck/src/check/upvar.rs231
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs372
-rw-r--r--compiler/rustc_typeck/src/collect/type_of.rs4
-rw-r--r--compiler/rustc_typeck/src/lib.rs1
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/rc.rs2
-rw-r--r--library/alloc/src/slice.rs4
-rw-r--r--library/alloc/src/str.rs2
-rw-r--r--library/core/src/num/mod.rs71
-rw-r--r--library/core/src/num/uint_macros.rs15
-rw-r--r--library/proc_macro/src/lib.rs12
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/os/raw/mod.rs9
-rw-r--r--library/std/src/sys/itron/thread.rs2
-rw-r--r--library/std/src/sys/windows/thread_local_dtor.rs26
-rw-r--r--library/std/src/sys/windows/thread_local_key.rs2
-rw-r--r--library/std/src/thread/mod.rs9
-rw-r--r--library/std/src/thread/tests.rs36
-rw-r--r--library/test/src/formatters/junit.rs4
-rw-r--r--src/bootstrap/builder.rs1
-rw-r--r--src/bootstrap/compile.rs6
-rw-r--r--src/bootstrap/doc.rs1
-rw-r--r--src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile27
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile27
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh13
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh13
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-x86_64-linux/download-openssl-curl.sh10
-rw-r--r--src/ci/docker/host-x86_64/shared/ISRG_Root_X1.crt31
-rwxr-xr-xsrc/ci/docker/run.sh3
-rwxr-xr-xsrc/ci/docker/scripts/freebsd-toolchain.sh2
-rw-r--r--src/doc/rustdoc/src/SUMMARY.md1
-rw-r--r--src/doc/rustdoc/src/how-to-read-rustdoc.md107
-rw-r--r--src/doc/unstable-book/src/library-features/asm.md4
-rw-r--r--src/librustdoc/clean/types.rs9
-rw-r--r--src/librustdoc/fold.rs78
-rw-r--r--src/librustdoc/html/highlight.rs8
-rw-r--r--src/librustdoc/html/render/context.rs6
-rw-r--r--src/librustdoc/html/render/mod.rs33
-rw-r--r--src/librustdoc/html/render/span_map.rs10
-rw-r--r--src/librustdoc/html/sources.rs60
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css3
-rw-r--r--src/librustdoc/html/static/js/main.js9
-rw-r--r--src/librustdoc/html/templates/page.html6
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/librustdoc/passes/bare_urls.rs13
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs23
-rw-r--r--src/librustdoc/passes/check_code_block_syntax.rs11
-rw-r--r--src/librustdoc/passes/check_doc_test_visibility.rs12
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs22
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs30
-rw-r--r--src/librustdoc/passes/html_tags.rs22
-rw-r--r--src/librustdoc/scrape_examples.rs36
-rw-r--r--src/librustdoc/visit.rs71
-rw-r--r--src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile18
-rw-r--r--src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs27
-rw-r--r--src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs12
-rw-r--r--src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs39
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs4
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs6
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-ordering/src/lib.rs5
-rw-r--r--src/test/rustdoc-gui/headings.goml3
-rw-r--r--src/test/rustdoc-gui/sidebar.goml28
-rw-r--r--src/test/rustdoc/doc-auto-cfg.rs8
-rw-r--r--src/test/rustdoc/doc-cfg-hide.rs2
-rw-r--r--src/test/rustdoc/doc-cfg-implicit.rs2
-rw-r--r--src/test/rustdoc/feature-gate-doc_auto_cfg.rs8
-rw-r--r--src/test/ui/closures/2229_closure_analysis/issue-90465.fixed35
-rw-r--r--src/test/ui/closures/2229_closure_analysis/issue-90465.rs34
-rw-r--r--src/test/ui/closures/2229_closure_analysis/issue-90465.stderr26
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed13
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs13
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr19
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed5
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs5
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr7
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed26
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs26
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr35
-rw-r--r--src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr2
-rw-r--r--src/test/ui/closures/print/closure-print-generic-verbose-2.stderr2
-rw-r--r--src/test/ui/closures/print/closure-print-verbose.stderr2
-rw-r--r--src/test/ui/consts/qualif-indirect-mutation-fail.rs20
-rw-r--r--src/test/ui/consts/qualif-indirect-mutation-fail.stderr36
-rw-r--r--src/test/ui/consts/qualif-indirect-mutation-pass.rs8
-rw-r--r--src/test/ui/extern/extern-methods.rs2
-rw-r--r--src/test/ui/extern/extern-thiscall.rs2
-rw-r--r--src/test/ui/extern/extern-vectorcall.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs10
-rw-r--r--src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr14
-rw-r--r--src/test/ui/generic-associated-types/collections-project-default.rs2
-rw-r--r--src/test/ui/generic-associated-types/collections.rs2
-rw-r--r--src/test/ui/generic-associated-types/generic-associated-type-bounds.rs2
-rw-r--r--src/test/ui/generic-associated-types/issue-70303.rs2
-rw-r--r--src/test/ui/generic-associated-types/issue-76535.rs2
-rw-r--r--src/test/ui/generic-associated-types/issue-76535.stderr6
-rw-r--r--src/test/ui/generic-associated-types/issue-79422.rs4
-rw-r--r--src/test/ui/generic-associated-types/issue-79422.stderr6
-rw-r--r--src/test/ui/generic-associated-types/issue-86787.rs5
-rw-r--r--src/test/ui/generic-associated-types/issue-86787.stderr36
-rw-r--r--src/test/ui/generic-associated-types/issue-88287.rs4
-rw-r--r--src/test/ui/generic-associated-types/issue-88360.rs3
-rw-r--r--src/test/ui/generic-associated-types/issue-88360.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-88459.rs19
-rw-r--r--src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs2
-rw-r--r--src/test/ui/generic-associated-types/self-outlives-lint.rs173
-rw-r--r--src/test/ui/generic-associated-types/self-outlives-lint.stderr98
-rw-r--r--src/test/ui/generic-associated-types/streaming_iterator.rs8
-rw-r--r--src/test/ui/generic-associated-types/variance_constraints.rs2
-rw-r--r--src/test/ui/hello2021.rs1
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs (renamed from src/test/ui/issues/issue-44005.rs)3
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs2
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr31
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs4
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr20
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr92
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr8
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs64
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs30
-rw-r--r--src/test/ui/hrtb/issue-90177.rs32
-rw-r--r--src/test/ui/issues/issue-44005.stderr20
-rw-r--r--src/test/ui/iterators/into-iter-on-arrays-2021.rs1
-rw-r--r--src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed9
-rw-r--r--src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr29
-rw-r--r--src/test/ui/lifetimes/issue-90170-elision-mismatch.rs9
-rw-r--r--src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr45
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr6
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr12
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr6
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr6
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr6
-rw-r--r--src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs2
-rw-r--r--src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs2
-rw-r--r--src/test/ui/lint/force-warn/warn-by-default-lint-two-modules.rs2
-rw-r--r--src/test/ui/lint/force-warn/warnings-lint-group.rs2
-rw-r--r--src/test/ui/lint/force-warn/warnings-lint-group.stderr4
-rw-r--r--src/test/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs9
-rw-r--r--src/test/ui/lint/unused_parens_json_suggestion.fixed2
-rw-r--r--src/test/ui/lint/unused_parens_json_suggestion.rs2
-rw-r--r--src/test/ui/lint/unused_parens_json_suggestion.stderr2
-rw-r--r--src/test/ui/lint/unused_parens_remove_json_suggestion.fixed2
-rw-r--r--src/test/ui/lint/unused_parens_remove_json_suggestion.rs2
-rw-r--r--src/test/ui/lint/unused_parens_remove_json_suggestion.stderr18
-rw-r--r--src/test/ui/matches2021.rs1
-rw-r--r--src/test/ui/mir-dataflow/indirect-mutation-offset.rs48
-rw-r--r--src/test/ui/mir-dataflow/indirect-mutation-offset.stderr10
-rw-r--r--src/test/ui/privacy/pub-priv-dep/pub-priv1.rs1
-rw-r--r--src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr8
-rw-r--r--src/test/ui/proc-macro/auxiliary/api/parse.rs10
-rw-r--r--src/test/ui/rust-2021/prelude2021.rs1
-rw-r--r--src/test/ui/rust-2021/reserved-prefixes-migration.fixed2
-rw-r--r--src/test/ui/rust-2021/reserved-prefixes-migration.rs2
-rw-r--r--src/test/ui/suggestions/undeclared-module-alloc.rs5
-rw-r--r--src/test/ui/suggestions/undeclared-module-alloc.stderr11
-rw-r--r--src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr6
-rw-r--r--src/test/ui/unsized/unchanged-param.rs1
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/.cargo/config.toml (renamed from src/tools/clippy/.cargo/config)0
-rw-r--r--src/tools/clippy/.github/deploy.sh3
-rw-r--r--src/tools/clippy/CHANGELOG.md166
-rw-r--r--src/tools/clippy/CONTRIBUTING.md4
-rw-r--r--src/tools/clippy/Cargo.toml6
-rw-r--r--src/tools/clippy/clippy_dev/src/new_lint.rs40
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs79
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/deprecated_lints.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc.rs48
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_variants.rs58
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/format.rs34
-rw-r--r--src/tools/clippy/clippy_lints/src/if_not_else.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/int_plus_one.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs68
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_all.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_correctness.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_lints.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_nursery.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_restriction.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_style.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/utils.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_assert.rs (renamed from src/tools/clippy/clippy_lints/src/if_then_panic.rs)35
-rw-r--r--src/tools/clippy/clippy_lints/src/match_str_case_mismatch.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/matches.rs75
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/mod.rs41
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/unseparated_literal_suffix.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/module_style.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrow.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs53
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs106
-rw-r--r--src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/unicode.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_hash.rs77
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap_in_result.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs13
-rw-r--r--src/tools/clippy/clippy_utils/src/camel_case.rs117
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs59
-rw-r--r--src/tools/clippy/clippy_utils/src/diagnostics.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/higher.rs28
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs31
-rw-r--r--src/tools/clippy/clippy_utils/src/str_utils.rs230
-rw-r--r--src/tools/clippy/doc/adding_lints.md48
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/tests/compile-test.rs5
-rw-r--r--src/tools/clippy/tests/missing-test-files.rs35
-rw-r--r--src/tools/clippy/tests/ui-toml/functions_maxlines/test.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/functions_maxlines/test.stderr8
-rw-r--r--src/tools/clippy/tests/ui/assertions_on_constants.rs4
-rw-r--r--src/tools/clippy/tests/ui/assertions_on_constants.stderr19
-rw-r--r--src/tools/clippy/tests/ui/async_yields_async.fixed1
-rw-r--r--src/tools/clippy/tests/ui/async_yields_async.rs1
-rw-r--r--src/tools/clippy/tests/ui/async_yields_async.stderr12
-rw-r--r--src/tools/clippy/tests/ui/await_holding_lock.rs1
-rw-r--r--src/tools/clippy/tests/ui/await_holding_lock.stderr16
-rw-r--r--src/tools/clippy/tests/ui/await_holding_refcell_ref.rs1
-rw-r--r--src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr24
-rw-r--r--src/tools/clippy/tests/ui/cast.rs23
-rw-r--r--src/tools/clippy/tests/ui/cast.stderr14
-rw-r--r--src/tools/clippy/tests/ui/crashes/auxiliary/ice-7868-aux.rs3
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-3969.rs5
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-3969.stderr44
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-5207.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6252.rs1
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6252.stderr12
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7231.rs1
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7868.rs7
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7868.stderr15
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7869.rs7
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7869.stderr15
-rw-r--r--src/tools/clippy/tests/ui/crashes/used_underscore_binding_macro.rs2
-rw-r--r--src/tools/clippy/tests/ui/debug_assert_with_mut_call.rs2
-rw-r--r--src/tools/clippy/tests/ui/deprecated.rs33
-rw-r--r--src/tools/clippy/tests/ui/deprecated.stderr128
-rw-r--r--src/tools/clippy/tests/ui/diverging_sub_expression.rs1
-rw-r--r--src/tools/clippy/tests/ui/diverging_sub_expression.stderr22
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.fixed215
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.rs (renamed from src/tools/clippy/tests/ui/doc/doc.rs)19
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.stderr184
-rw-r--r--src/tools/clippy/tests/ui/doc/doc.stderr190
-rw-r--r--src/tools/clippy/tests/ui/doc/issue_1832.rs9
-rw-r--r--src/tools/clippy/tests/ui/doc/issue_902.rs7
-rw-r--r--src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr12
-rw-r--r--src/tools/clippy/tests/ui/doc_errors.rs1
-rw-r--r--src/tools/clippy/tests/ui/doc_errors.stderr14
-rw-r--r--src/tools/clippy/tests/ui/doc_unsafe.rs5
-rw-r--r--src/tools/clippy/tests/ui/enum_variants.stderr2
-rw-r--r--src/tools/clippy/tests/ui/eval_order_dependence.rs2
-rw-r--r--src/tools/clippy/tests/ui/eval_order_dependence.stderr16
-rw-r--r--src/tools/clippy/tests/ui/fallible_impl_from.rs1
-rw-r--r--src/tools/clippy/tests/ui/fallible_impl_from.stderr22
-rw-r--r--src/tools/clippy/tests/ui/format.fixed2
-rw-r--r--src/tools/clippy/tests/ui/format.rs2
-rw-r--r--src/tools/clippy/tests/ui/format.stderr28
-rw-r--r--src/tools/clippy/tests/ui/format_args.fixed12
-rw-r--r--src/tools/clippy/tests/ui/format_args.rs12
-rw-r--r--src/tools/clippy/tests/ui/format_args.stderr60
-rw-r--r--src/tools/clippy/tests/ui/format_args_unfixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/future_not_send.rs1
-rw-r--r--src/tools/clippy/tests/ui/future_not_send.stderr36
-rw-r--r--src/tools/clippy/tests/ui/if_not_else.rs10
-rw-r--r--src/tools/clippy/tests/ui/if_not_else.stderr4
-rw-r--r--src/tools/clippy/tests/ui/implicit_hasher.rs1
-rw-r--r--src/tools/clippy/tests/ui/implicit_hasher.stderr24
-rw-r--r--src/tools/clippy/tests/ui/implicit_return.fixed1
-rw-r--r--src/tools/clippy/tests/ui/implicit_return.rs1
-rw-r--r--src/tools/clippy/tests/ui/implicit_return.stderr32
-rw-r--r--src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed1
-rw-r--r--src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs1
-rw-r--r--src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr4
-rw-r--r--src/tools/clippy/tests/ui/issue-7447.stderr19
-rw-r--r--src/tools/clippy/tests/ui/issue_4266.rs1
-rw-r--r--src/tools/clippy/tests/ui/issue_4266.stderr4
-rw-r--r--src/tools/clippy/tests/ui/len_without_is_empty.rs2
-rw-r--r--src/tools/clippy/tests/ui/len_without_is_empty.stderr34
-rw-r--r--src/tools/clippy/tests/ui/literals.rs3
-rw-r--r--src/tools/clippy/tests/ui/literals.stderr74
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports.fixed1
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports.rs1
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports.stderr14
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2018.fixed (renamed from src/tools/clippy/tests/ui/if_then_panic.fixed)5
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2018.stderr (renamed from src/tools/clippy/tests/ui/if_then_panic.stderr)16
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2021.fixed43
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2021.stderr60
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.fixed43
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.rs (renamed from src/tools/clippy/tests/ui/if_then_panic.rs)5
-rw-r--r--src/tools/clippy/tests/ui/manual_async_fn.fixed1
-rw-r--r--src/tools/clippy/tests/ui/manual_async_fn.rs1
-rw-r--r--src/tools/clippy/tests/ui/manual_async_fn.stderr20
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option.fixed1
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option.rs1
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option.stderr42
-rw-r--r--src/tools/clippy/tests/ui/match_overlapping_arm.rs7
-rw-r--r--src/tools/clippy/tests/ui/match_ref_pats.rs2
-rw-r--r--src/tools/clippy/tests/ui/match_str_case_mismatch.rs86
-rw-r--r--src/tools/clippy/tests/ui/match_str_case_mismatch.stderr52
-rw-r--r--src/tools/clippy/tests/ui/match_wild_err_arm.edition2018.stderr (renamed from src/tools/clippy/tests/ui/match_wild_err_arm.stderr)8
-rw-r--r--src/tools/clippy/tests/ui/match_wild_err_arm.edition2021.stderr35
-rw-r--r--src/tools/clippy/tests/ui/match_wild_err_arm.rs3
-rw-r--r--src/tools/clippy/tests/ui/methods.rs1
-rw-r--r--src/tools/clippy/tests/ui/methods.stderr4
-rw-r--r--src/tools/clippy/tests/ui/missing-doc.rs9
-rw-r--r--src/tools/clippy/tests/ui/missing-doc.stderr48
-rw-r--r--src/tools/clippy/tests/ui/missing_panics_doc.rs1
-rw-r--r--src/tools/clippy/tests/ui/missing_panics_doc.stderr34
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow_pat.rs1
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow_pat.stderr24
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.rs5
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.stderr44
-rw-r--r--src/tools/clippy/tests/ui/needless_return.fixed1
-rw-r--r--src/tools/clippy/tests/ui/needless_return.rs1
-rw-r--r--src/tools/clippy/tests/ui/needless_return.stderr64
-rw-r--r--src/tools/clippy/tests/ui/non_expressive_names.rs4
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.fixed1
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.rs1
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.stderr28
-rw-r--r--src/tools/clippy/tests/ui/panic_in_result_fn.rs1
-rw-r--r--src/tools/clippy/tests/ui/panic_in_result_fn.stderr28
-rw-r--r--src/tools/clippy/tests/ui/ptr_arg.rs11
-rw-r--r--src/tools/clippy/tests/ui/ptr_arg.stderr24
-rw-r--r--src/tools/clippy/tests/ui/question_mark.fixed21
-rw-r--r--src/tools/clippy/tests/ui/question_mark.rs21
-rw-r--r--src/tools/clippy/tests/ui/question_mark.stderr4
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.stderr14
-rw-r--r--src/tools/clippy/tests/ui/ref_binding_to_reference.rs1
-rw-r--r--src/tools/clippy/tests/ui/ref_binding_to_reference.stderr14
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed57
-rw-r--r--src/tools/clippy/tests/ui/rename.rs57
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr188
-rw-r--r--src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs2
-rw-r--r--src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs2
-rw-r--r--src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr28
-rw-r--r--src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs2
-rw-r--r--src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr30
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports.fixed1
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports.rs1
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports.stderr4
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports_macro.fixed1
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports_macro.rs1
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports_macro.stderr2
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports_nested_first.rs1
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr6
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports_self_after.rs1
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports_self_before.rs1
-rw-r--r--src/tools/clippy/tests/ui/string_slice.rs10
-rw-r--r--src/tools/clippy/tests/ui/string_slice.stderr22
-rw-r--r--src/tools/clippy/tests/ui/unit_hash.rs27
-rw-r--r--src/tools/clippy/tests/ui/unit_hash.stderr27
-rw-r--r--src/tools/clippy/tests/ui/unused_async.rs1
-rw-r--r--src/tools/clippy/tests/ui/unused_async.stderr2
-rw-r--r--src/tools/clippy/tests/ui/use_self.fixed1
-rw-r--r--src/tools/clippy/tests/ui/use_self.rs1
-rw-r--r--src/tools/clippy/tests/ui/use_self.stderr56
-rw-r--r--src/tools/clippy/tests/ui/used_underscore_binding.rs1
-rw-r--r--src/tools/clippy/tests/ui/used_underscore_binding.stderr12
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports.fixed7
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports.rs7
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports.stderr42
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_convention.rs1
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_convention.stderr48
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_convention2.rs1
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_convention2.stderr4
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs1
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr4
-rw-r--r--src/tools/compiletest/src/header.rs3
-rw-r--r--src/tools/compiletest/src/header/tests.rs2
-rw-r--r--src/tools/compiletest/src/runtest.rs3
m---------src/tools/rust-analyzer39
-rw-r--r--src/tools/rustdoc-js/tester.js10
-rw-r--r--src/tools/tidy/src/features.rs1
-rw-r--r--triagebot.toml2
438 files changed, 6022 insertions, 2636 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 43da32df5d9..6f95dae42a4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -576,7 +576,7 @@ dependencies = [
 name = "clippy"
 version = "0.1.58"
 dependencies = [
- "cargo_metadata 0.12.0",
+ "cargo_metadata 0.14.0",
  "clippy_lints",
  "clippy_utils",
  "compiletest_rs",
@@ -588,7 +588,7 @@ dependencies = [
  "regex",
  "rustc-workspace-hack",
  "rustc_tools_util 0.2.0",
- "semver 0.11.0",
+ "semver 1.0.3",
  "serde",
  "syn",
  "tempfile",
@@ -613,7 +613,7 @@ dependencies = [
 name = "clippy_lints"
 version = "0.1.58"
 dependencies = [
- "cargo_metadata 0.12.0",
+ "cargo_metadata 0.14.0",
  "clippy_utils",
  "if_chain",
  "itertools 0.10.1",
@@ -621,7 +621,7 @@ dependencies = [
  "quine-mc_cluskey",
  "regex-syntax",
  "rustc-semver",
- "semver 0.11.0",
+ "semver 1.0.3",
  "serde",
  "serde_json",
  "toml",
@@ -710,9 +710,9 @@ dependencies = [
 
 [[package]]
 name = "compiletest_rs"
-version = "0.7.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64698e5e2435db061a85e6320af12c30c5fd88eb84b35d2c1e03ce4f143255ca"
+checksum = "29843cb8d351febf86557681d049d1e1652b81a086a190fa1173c07fd17fbf83"
 dependencies = [
  "diff",
  "filetime",
@@ -1900,9 +1900,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 [[package]]
 name = "libc"
-version = "0.2.103"
+version = "0.2.106"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
+checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673"
 dependencies = [
  "rustc-std-workspace-core",
 ]
diff --git a/compiler/rustc_ast/README.md b/compiler/rustc_ast/README.md
index dd407dba1f4..b2b90fed033 100644
--- a/compiler/rustc_ast/README.md
+++ b/compiler/rustc_ast/README.md
@@ -1,6 +1,5 @@
 The `rustc_ast` crate contains those things concerned purely with syntax
-– that is, the AST ("abstract syntax tree"), parser, pretty-printer,
-lexer, macro expander, and utilities for traversing ASTs.
+– that is, the AST ("abstract syntax tree"), along with some definitions for tokens and token streams, data structures/traits for mutating ASTs, and shared definitions for other AST-related parts of the compiler (like the lexer and macro-expansion).
 
 For more information about how these things work in rustc, see the
 rustc dev guide:
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index e3c610585d9..b9db2a7e089 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -1,4 +1,4 @@
-//! The Rust parser and macro expander.
+//! The Rust Abstract Syntax Tree (AST).
 //!
 //! # Note
 //!
@@ -16,6 +16,7 @@
 #![feature(nll)]
 #![feature(min_specialization)]
 #![recursion_limit = "256"]
+#![feature(slice_internals)]
 
 #[macro_use]
 extern crate rustc_macros;
@@ -25,6 +26,7 @@ pub mod util {
     pub mod comments;
     pub mod literal;
     pub mod parser;
+    pub mod unicode;
 }
 
 pub mod ast;
diff --git a/compiler/rustc_ast/src/util/unicode.rs b/compiler/rustc_ast/src/util/unicode.rs
new file mode 100644
index 00000000000..f009f7b300c
--- /dev/null
+++ b/compiler/rustc_ast/src/util/unicode.rs
@@ -0,0 +1,35 @@
+pub const TEXT_FLOW_CONTROL_CHARS: &[char] = &[
+    '\u{202A}', '\u{202B}', '\u{202D}', '\u{202E}', '\u{2066}', '\u{2067}', '\u{2068}', '\u{202C}',
+    '\u{2069}',
+];
+
+#[inline]
+pub fn contains_text_flow_control_chars(s: &str) -> bool {
+    // Char   - UTF-8
+    // U+202A - E2 80 AA
+    // U+202B - E2 80 AB
+    // U+202C - E2 80 AC
+    // U+202D - E2 80 AD
+    // U+202E - E2 80 AE
+    // U+2066 - E2 81 A6
+    // U+2067 - E2 81 A7
+    // U+2068 - E2 81 A8
+    // U+2069 - E2 81 A9
+    let mut bytes = s.as_bytes();
+    loop {
+        match core::slice::memchr::memchr(0xE2, &bytes) {
+            Some(idx) => {
+                // bytes are valid UTF-8 -> E2 must be followed by two bytes
+                let ch = &bytes[idx..idx + 3];
+                match ch {
+                    [_, 0x80, 0xAA..=0xAE] | [_, 0x81, 0xA6..=0xA9] => break true,
+                    _ => {}
+                }
+                bytes = &bytes[idx + 3..];
+            }
+            None => {
+                break false;
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index dca9c1f04d3..bedd3523d89 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -1,7 +1,6 @@
 use crate::builder::Builder;
 use crate::context::CodegenCx;
 use crate::llvm::{self, AttributePlace};
-use crate::llvm_util;
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
@@ -53,15 +52,10 @@ pub trait ArgAttributesExt {
 }
 
 fn should_use_mutable_noalias(cx: &CodegenCx<'_, '_>) -> bool {
-    // LLVM prior to version 12 has known miscompiles in the presence of
-    // noalias attributes (see #54878). Only enable mutable noalias by
-    // default for versions we believe to be safe.
-    cx.tcx
-        .sess
-        .opts
-        .debugging_opts
-        .mutable_noalias
-        .unwrap_or_else(|| llvm_util::get_version() >= (12, 0, 0))
+    // LLVM prior to version 12 had known miscompiles in the presence of
+    // noalias attributes (see #54878), but we don't support earlier
+    // versions at all anymore. We now enable mutable noalias by default.
+    cx.tcx.sess.opts.debugging_opts.mutable_noalias.unwrap_or(true)
 }
 
 impl ArgAttributesExt for ArgAttributes {
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 0707faf610c..6c74163fb49 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -731,7 +731,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     }
 
     fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> {
-        if llvm_util::get_version() >= (12, 0, 0) && !self.fptoint_sat_broken_in_llvm() {
+        if !self.fptoint_sat_broken_in_llvm() {
             let src_ty = self.cx.val_ty(val);
             let float_width = self.cx.float_width(src_ty);
             let int_width = self.cx.int_width(dest_ty);
@@ -743,7 +743,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     }
 
     fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> {
-        if llvm_util::get_version() >= (12, 0, 0) && !self.fptoint_sat_broken_in_llvm() {
+        if !self.fptoint_sat_broken_in_llvm() {
             let src_ty = self.cx.val_ty(val);
             let float_width = self.cx.float_width(src_ty);
             let int_width = self.cx.int_width(dest_ty);
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index cda766039c1..1dba264a961 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -134,9 +134,6 @@ pub unsafe fn create_module(
     let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
 
     let mut target_data_layout = sess.target.data_layout.clone();
-    if llvm_util::get_version() < (12, 0, 0) && sess.target.arch == "powerpc64" {
-        target_data_layout = target_data_layout.replace("-v256:256:256-v512:512:512", "");
-    }
     if llvm_util::get_version() < (13, 0, 0) {
         if sess.target.arch == "powerpc64" {
             target_data_layout = target_data_layout.replace("-S128", "");
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 8f4d79e7147..64fedb7bc1a 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -76,6 +76,27 @@ mod value;
 #[derive(Clone)]
 pub struct LlvmCodegenBackend(());
 
+struct TimeTraceProfiler {
+    enabled: bool,
+}
+
+impl TimeTraceProfiler {
+    fn new(enabled: bool) -> Self {
+        if enabled {
+            unsafe { llvm::LLVMTimeTraceProfilerInitialize() }
+        }
+        TimeTraceProfiler { enabled }
+    }
+}
+
+impl Drop for TimeTraceProfiler {
+    fn drop(&mut self) {
+        if self.enabled {
+            unsafe { llvm::LLVMTimeTraceProfilerFinishThread() }
+        }
+    }
+}
+
 impl ExtraBackendMethods for LlvmCodegenBackend {
     fn new_metadata(&self, tcx: TyCtxt<'_>, mod_name: &str) -> ModuleLlvm {
         ModuleLlvm::new_metadata(tcx, mod_name)
@@ -119,6 +140,34 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
     fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str> {
         llvm_util::tune_cpu(sess)
     }
+
+    fn spawn_thread<F, T>(time_trace: bool, f: F) -> std::thread::JoinHandle<T>
+    where
+        F: FnOnce() -> T,
+        F: Send + 'static,
+        T: Send + 'static,
+    {
+        std::thread::spawn(move || {
+            let _profiler = TimeTraceProfiler::new(time_trace);
+            f()
+        })
+    }
+
+    fn spawn_named_thread<F, T>(
+        time_trace: bool,
+        name: String,
+        f: F,
+    ) -> std::io::Result<std::thread::JoinHandle<T>>
+    where
+        F: FnOnce() -> T,
+        F: Send + 'static,
+        T: Send + 'static,
+    {
+        std::thread::Builder::new().name(name).spawn(move || {
+            let _profiler = TimeTraceProfiler::new(time_trace);
+            f()
+        })
+    }
 }
 
 impl WriteBackendMethods for LlvmCodegenBackend {
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 21d2388fc30..749eec459ac 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1737,6 +1737,8 @@ extern "C" {
 
     pub fn LLVMTimeTraceProfilerInitialize();
 
+    pub fn LLVMTimeTraceProfilerFinishThread();
+
     pub fn LLVMTimeTraceProfilerFinish(FileName: *const c_char);
 
     pub fn LLVMAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>);
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index baa257069aa..c3e7e7169a9 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -113,11 +113,6 @@ unsafe fn configure_llvm(sess: &Session) {
     }
 
     if sess.opts.debugging_opts.llvm_time_trace {
-        // time-trace is not thread safe and running it in parallel will cause seg faults.
-        if !sess.opts.debugging_opts.no_parallel_llvm {
-            bug!("`-Z llvm-time-trace` requires `-Z no-parallel-llvm")
-        }
-
         llvm::LLVMTimeTraceProfilerInitialize();
     }
 
@@ -180,6 +175,7 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> Vec<&'a str> {
         ("aarch64", "dpb2") => vec!["ccdp"],
         ("aarch64", "frintts") => vec!["fptoint"],
         ("aarch64", "fcma") => vec!["complxnum"],
+        ("aarch64", "pmuv3") => vec!["perfmon"],
         (_, s) => vec![s],
     }
 }
@@ -405,11 +401,6 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
     // -Ctarget-features
     features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter));
 
-    // FIXME: Move outline-atomics to target definition when earliest supported LLVM is 12.
-    if get_version() >= (12, 0, 0) && sess.target.llvm_target.contains("aarch64-unknown-linux") {
-        features.push("+outline-atomics".to_string());
-    }
-
     features
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index da34612ce76..b2edc6c0183 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -310,6 +310,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
     pub no_landing_pads: bool,
     pub save_temps: bool,
     pub fewer_names: bool,
+    pub time_trace: bool,
     pub exported_symbols: Option<Arc<ExportedSymbols>>,
     pub opts: Arc<config::Options>,
     pub crate_types: Vec<CrateType>,
@@ -1039,6 +1040,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
         no_landing_pads: sess.panic_strategy() == PanicStrategy::Abort,
         fewer_names: sess.fewer_names(),
         save_temps: sess.opts.cg.save_temps,
+        time_trace: sess.opts.debugging_opts.llvm_time_trace,
         opts: Arc::new(sess.opts.clone()),
         prof: sess.prof.clone(),
         exported_symbols,
@@ -1198,7 +1200,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
     // Each LLVM module is automatically sent back to the coordinator for LTO if
     // necessary. There's already optimizations in place to avoid sending work
     // back to the coordinator if LTO isn't requested.
-    return thread::spawn(move || {
+    return B::spawn_thread(cgcx.time_trace, move || {
         let mut worker_id_counter = 0;
         let mut free_worker_ids = Vec::new();
         let mut get_worker_id = |free_worker_ids: &mut Vec<usize>| {
@@ -1615,59 +1617,57 @@ fn start_executing_work<B: ExtraBackendMethods>(
 pub struct WorkerFatalError;
 
 fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B>) {
-    let builder = thread::Builder::new().name(work.short_description());
-    builder
-        .spawn(move || {
-            // Set up a destructor which will fire off a message that we're done as
-            // we exit.
-            struct Bomb<B: ExtraBackendMethods> {
-                coordinator_send: Sender<Box<dyn Any + Send>>,
-                result: Option<Result<WorkItemResult<B>, FatalError>>,
-                worker_id: usize,
-            }
-            impl<B: ExtraBackendMethods> Drop for Bomb<B> {
-                fn drop(&mut self) {
-                    let worker_id = self.worker_id;
-                    let msg = match self.result.take() {
-                        Some(Ok(WorkItemResult::Compiled(m))) => {
-                            Message::Done::<B> { result: Ok(m), worker_id }
-                        }
-                        Some(Ok(WorkItemResult::NeedsLink(m))) => {
-                            Message::NeedsLink::<B> { module: m, worker_id }
-                        }
-                        Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
-                            Message::NeedsFatLTO::<B> { result: m, worker_id }
-                        }
-                        Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
-                            Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
-                        }
-                        Some(Err(FatalError)) => {
-                            Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
-                        }
-                        None => Message::Done::<B> { result: Err(None), worker_id },
-                    };
-                    drop(self.coordinator_send.send(Box::new(msg)));
-                }
+    B::spawn_named_thread(cgcx.time_trace, work.short_description(), move || {
+        // Set up a destructor which will fire off a message that we're done as
+        // we exit.
+        struct Bomb<B: ExtraBackendMethods> {
+            coordinator_send: Sender<Box<dyn Any + Send>>,
+            result: Option<Result<WorkItemResult<B>, FatalError>>,
+            worker_id: usize,
+        }
+        impl<B: ExtraBackendMethods> Drop for Bomb<B> {
+            fn drop(&mut self) {
+                let worker_id = self.worker_id;
+                let msg = match self.result.take() {
+                    Some(Ok(WorkItemResult::Compiled(m))) => {
+                        Message::Done::<B> { result: Ok(m), worker_id }
+                    }
+                    Some(Ok(WorkItemResult::NeedsLink(m))) => {
+                        Message::NeedsLink::<B> { module: m, worker_id }
+                    }
+                    Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
+                        Message::NeedsFatLTO::<B> { result: m, worker_id }
+                    }
+                    Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
+                        Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
+                    }
+                    Some(Err(FatalError)) => {
+                        Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
+                    }
+                    None => Message::Done::<B> { result: Err(None), worker_id },
+                };
+                drop(self.coordinator_send.send(Box::new(msg)));
             }
+        }
 
-            let mut bomb = Bomb::<B> {
-                coordinator_send: cgcx.coordinator_send.clone(),
-                result: None,
-                worker_id: cgcx.worker,
-            };
+        let mut bomb = Bomb::<B> {
+            coordinator_send: cgcx.coordinator_send.clone(),
+            result: None,
+            worker_id: cgcx.worker,
+        };
 
-            // Execute the work itself, and if it finishes successfully then flag
-            // ourselves as a success as well.
-            //
-            // Note that we ignore any `FatalError` coming out of `execute_work_item`,
-            // as a diagnostic was already sent off to the main thread - just
-            // surface that there was an error in this worker.
-            bomb.result = {
-                let _prof_timer = work.start_profiling(&cgcx);
-                Some(execute_work_item(&cgcx, work))
-            };
-        })
-        .expect("failed to spawn thread");
+        // Execute the work itself, and if it finishes successfully then flag
+        // ourselves as a success as well.
+        //
+        // Note that we ignore any `FatalError` coming out of `execute_work_item`,
+        // as a diagnostic was already sent off to the main thread - just
+        // surface that there was an error in this worker.
+        bomb.result = {
+            let _prof_timer = work.start_profiling(&cgcx);
+            Some(execute_work_item(&cgcx, work))
+        };
+    })
+    .expect("failed to spawn thread");
 }
 
 enum SharedEmitterMessage {
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 297dcde99b3..a9471f7b771 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -832,7 +832,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             // FIXME(rcvalle): Add support for generalized identifiers.
             // FIXME(rcvalle): Create distinct unnamed MDNodes for internal identifiers.
             let typeid = typeid_for_fnabi(bx.tcx(), fn_abi);
-            let typeid_metadata = bx.typeid_metadata(typeid.clone());
+            let typeid_metadata = bx.typeid_metadata(typeid);
 
             // Test whether the function pointer is associated with the type identifier.
             let cond = bx.type_test(fn_ptr, typeid_metadata);
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 1cd400eecfb..1ef863e84af 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -250,7 +250,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     // is associated with a type identifier).
     if cx.tcx().sess.is_sanitizer_cfi_enabled() {
         let typeid = typeid_for_fnabi(cx.tcx(), fn_abi);
-        bx.type_metadata(llfn, typeid.clone());
+        bx.type_metadata(llfn, typeid);
     }
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs
index fe7f6288adb..2c96987d339 100644
--- a/compiler/rustc_codegen_ssa/src/mir/statement.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs
@@ -125,7 +125,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let count = self.codegen_operand(&mut bx, count).immediate();
                 let pointee_layout = dst_val
                     .layout
-                    .pointee_info_at(&mut bx, rustc_target::abi::Size::ZERO)
+                    .pointee_info_at(&bx, rustc_target::abi::Size::ZERO)
                     .expect("Expected pointer");
                 let bytes = bx.mul(count, bx.const_usize(pointee_layout.size.bytes()));
 
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index dbffb266be8..caeeb23feb4 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -36,7 +36,6 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("thumb-mode", Some(sym::arm_target_feature)),
 ];
 
-// Commented features are not available in LLVM 10.0, or have since been renamed
 const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     // FEAT_AdvSimd
     ("neon", Some(sym::aarch64_target_feature)),
@@ -67,13 +66,13 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     // FEAT_DIT
     ("dit", Some(sym::aarch64_target_feature)),
     // FEAT_FLAGM
-    // ("flagm", Some(sym::aarch64_target_feature)),
+    ("flagm", Some(sym::aarch64_target_feature)),
     // FEAT_SSBS
     ("ssbs", Some(sym::aarch64_target_feature)),
     // FEAT_SB
     ("sb", Some(sym::aarch64_target_feature)),
     // FEAT_PAUTH
-    // ("pauth", Some(sym::aarch64_target_feature)),
+    ("pauth", Some(sym::aarch64_target_feature)),
     // FEAT_DPB
     ("dpb", Some(sym::aarch64_target_feature)),
     // FEAT_DPB2
@@ -93,11 +92,11 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     // FEAT_I8MM
     ("i8mm", Some(sym::aarch64_target_feature)),
     // FEAT_F32MM
-    // ("f32mm", Some(sym::aarch64_target_feature)),
+    ("f32mm", Some(sym::aarch64_target_feature)),
     // FEAT_F64MM
-    // ("f64mm", Some(sym::aarch64_target_feature)),
+    ("f64mm", Some(sym::aarch64_target_feature)),
     // FEAT_BF16
-    // ("bf16", Some(sym::aarch64_target_feature)),
+    ("bf16", Some(sym::aarch64_target_feature)),
     // FEAT_RAND
     ("rand", Some(sym::aarch64_target_feature)),
     // FEAT_BTI
@@ -116,13 +115,23 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("sha3", Some(sym::aarch64_target_feature)),
     // FEAT_SM3 & FEAT_SM4
     ("sm4", Some(sym::aarch64_target_feature)),
+    // FEAT_PAN
+    ("pan", Some(sym::aarch64_target_feature)),
+    // FEAT_LOR
+    ("lor", Some(sym::aarch64_target_feature)),
+    // FEAT_VHE
+    ("vh", Some(sym::aarch64_target_feature)),
+    // FEAT_PMUv3
+    ("pmuv3", Some(sym::aarch64_target_feature)),
+    // FEAT_SPE
+    ("spe", Some(sym::aarch64_target_feature)),
     ("v8.1a", Some(sym::aarch64_target_feature)),
     ("v8.2a", Some(sym::aarch64_target_feature)),
     ("v8.3a", Some(sym::aarch64_target_feature)),
     ("v8.4a", Some(sym::aarch64_target_feature)),
     ("v8.5a", Some(sym::aarch64_target_feature)),
-    // ("v8.6a", Some(sym::aarch64_target_feature)),
-    // ("v8.7a", Some(sym::aarch64_target_feature)),
+    ("v8.6a", Some(sym::aarch64_target_feature)),
+    ("v8.7a", Some(sym::aarch64_target_feature)),
 ];
 
 const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index 8fef8314a5c..9c8bc3b2109 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -142,4 +142,26 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
     ) -> TargetMachineFactoryFn<Self>;
     fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str;
     fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str>;
+
+    fn spawn_thread<F, T>(_time_trace: bool, f: F) -> std::thread::JoinHandle<T>
+    where
+        F: FnOnce() -> T,
+        F: Send + 'static,
+        T: Send + 'static,
+    {
+        std::thread::spawn(f)
+    }
+
+    fn spawn_named_thread<F, T>(
+        _time_trace: bool,
+        name: String,
+        f: F,
+    ) -> std::io::Result<std::thread::JoinHandle<T>>
+    where
+        F: FnOnce() -> T,
+        F: Send + 'static,
+        T: Send + 'static,
+    {
+        std::thread::Builder::new().name(name).spawn(f)
+    }
 }
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
index 38576230883..fcce829eba4 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
@@ -94,11 +94,10 @@ where
         }
     }
 
-    fn address_of_allows_mutation(&self, mt: mir::Mutability, place: mir::Place<'tcx>) -> bool {
-        match mt {
-            mir::Mutability::Mut => true,
-            mir::Mutability::Not => self.shared_borrow_allows_mutation(place),
-        }
+    fn address_of_allows_mutation(&self, _mt: mir::Mutability, _place: mir::Place<'tcx>) -> bool {
+        // Exact set of permissions granted by AddressOf is undecided. Conservatively assume that
+        // it might allow mutation until resolution of #56604.
+        true
     }
 
     fn ref_allows_mutation(&self, kind: mir::BorrowKind, place: mir::Place<'tcx>) -> bool {
@@ -110,6 +109,15 @@ where
         }
     }
 
+    /// `&` only allow mutation if the borrowed place is `!Freeze`.
+    ///
+    /// This assumes that it is UB to take the address of a struct field whose type is
+    /// `Freeze`, then use pointer arithmetic to derive a pointer to a *different* field of
+    /// that same struct whose type is `!Freeze`. If we decide that this is not UB, we will
+    /// have to check the type of the borrowed **local** instead of the borrowed **place**
+    /// below. See [rust-lang/unsafe-code-guidelines#134].
+    ///
+    /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
     fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool {
         !place
             .ty(self.ccx.body, self.ccx.tcx)
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index 724e3f7fed3..42ce849c64d 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -487,9 +487,9 @@ E0785: include_str!("./error_codes/E0785.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
-//  E0019, merged into E0015
-//  E0035, merged into E0087/E0089
-//  E0036, merged into E0087/E0089
+//  E0019, // merged into E0015
+//  E0035, // merged into E0087/E0089
+//  E0036, // merged into E0087/E0089
 //  E0068,
 //  E0085,
 //  E0086,
@@ -504,8 +504,8 @@ E0785: include_str!("./error_codes/E0785.md"),
 //  E0134,
 //  E0135,
 //  E0141,
-//  E0153, unused error code
-//  E0157, unused error code
+//  E0153, // unused error code
+//  E0157, // unused error code
 //  E0159, // use of trait `{}` as struct constructor
 //  E0163, // merged into E0071
 //  E0167,
@@ -573,24 +573,24 @@ E0785: include_str!("./error_codes/E0785.md"),
            // between structures with the same definition
 //  E0385, // {} in an aliasable location
 //  E0402, // cannot use an outer type parameter in this context
-//  E0406, merged into 420
-//  E0410, merged into 408
-//  E0413, merged into 530
-//  E0414, merged into 530
-//  E0417, merged into 532
-//  E0418, merged into 532
-//  E0419, merged into 531
-//  E0420, merged into 532
-//  E0421, merged into 531
-//  E0427, merged into 530
+//  E0406, // merged into 420
+//  E0410, // merged into 408
+//  E0413, // merged into 530
+//  E0414, // merged into 530
+//  E0417, // merged into 532
+//  E0418, // merged into 532
+//  E0419, // merged into 531
+//  E0420, // merged into 532
+//  E0421, // merged into 531
+//  E0427, // merged into 530
 //  E0456, // plugin `..` is not available for triple `..`
     E0457, // plugin `..` only found in rlib format, but must be available...
     E0460, // found possibly newer version of crate `..`
     E0461, // couldn't find crate `..` with expected target triple ..
     E0462, // found staticlib `..` instead of rlib or dylib
     E0465, // multiple .. candidates for `..` found
-//  E0467, removed
-//  E0470, removed
+//  E0467, // removed
+//  E0470, // removed
 //  E0471, // constant evaluation error (in pattern)
     E0472, // llvm_asm! is unsupported on this target
 //  E0473, // dereference of reference outside its lifetime
@@ -610,8 +610,7 @@ E0785: include_str!("./error_codes/E0785.md"),
     E0490, // a value of type `..` is borrowed for too long
     E0514, // metadata version mismatch
     E0519, // local crate and dependency have same (crate-name, disambiguator)
-    // two dependencies have same (crate-name, disambiguator) but different SVH
-    E0523,
+    E0523, // two dependencies have same (crate-name, disambiguator) but different SVH
 //  E0526, // shuffle indices are not constant
 //  E0540, // multiple rustc_deprecated attributes
 //  E0548, // replaced with a generic attribute input check
@@ -638,7 +637,7 @@ E0785: include_str!("./error_codes/E0785.md"),
     E0711, // a feature has been declared with conflicting stability attributes
     E0717, // rustc_promotable without stability attribute
 //  E0721, // `await` keyword
-//  E0723, unstable feature in `const` context
+//  E0723, // unstable feature in `const` context
     E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
 //  E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
     E0772, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 0d7a2afb636..941d957103c 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -297,6 +297,8 @@ declare_features! (
     (accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119), None),
     /// Allows panicking during const eval (producing compile-time errors).
     (accepted, const_panic, "1.57.0", Some(51999), None),
+    /// Lessens the requirements for structs to implement `Unsize`.
+    (accepted, relaxed_struct_unsize, "1.58.0", Some(81793), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: accepted features
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 2bbfb561ba5..1c6f1344e8a 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -101,9 +101,13 @@ impl Feature {
     }
 }
 
+// See https://rustc-dev-guide.rust-lang.org/feature-gates.html#feature-gates for more
+// documentation about handling feature gates.
+//
 // If you change this, please modify `src/doc/unstable-book` as well.
 //
-// Don't ever remove anything from this list; move them to `removed.rs`.
+// Don't ever remove anything from this list; move them to `accepted.rs` if
+// accepted or `removed.rs` if removed.
 //
 // The version numbers here correspond to the version in which the current status
 // was set. This is most important for knowing when a particular feature became
@@ -589,9 +593,6 @@ declare_features! (
     /// Allows `extern "C-cmse-nonsecure-call" fn()`.
     (active, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391), None),
 
-    /// Lessens the requirements for structs to implement `Unsize`.
-    (active, relaxed_struct_unsize, "1.51.0", Some(81793), None),
-
     /// Allows associated types in inherent impls.
     (incomplete, inherent_associated_types, "1.52.0", Some(8995), None),
 
@@ -688,6 +689,9 @@ declare_features! (
     /// not changed from prior instances of the same struct (RFC #2528)
     (incomplete, type_changing_struct_update, "1.58.0", Some(86555), None),
 
+    /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
+    (active, doc_auto_cfg, "1.58.0", Some(43781), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
index 1b35c4032f4..ac57796763f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -7,7 +7,10 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::infer::SubregionOrigin;
 
-use rustc_errors::{struct_span_err, ErrorReported};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
+use rustc_hir as hir;
+use rustc_hir::{GenericParamKind, Ty};
+use rustc_middle::ty::Region;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when both the concerned regions are anonymous.
@@ -160,11 +163,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 }
             };
 
-        let mut e = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch");
+        let mut err = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch");
 
-        e.span_label(span_1, main_label);
-        e.span_label(span_2, String::new());
-        e.span_label(span, span_label);
+        err.span_label(span_1, main_label);
+        err.span_label(span_2, String::new());
+        err.span_label(span, span_label);
+
+        self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err);
 
         if let Some(t) = future_return_type {
             let snip = self
@@ -178,14 +183,87 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                     (_, "") => None,
                     _ => Some(s),
                 })
-                .unwrap_or("{unnamed_type}".to_string());
+                .unwrap_or_else(|| "{unnamed_type}".to_string());
 
-            e.span_label(
+            err.span_label(
                 t.span,
                 &format!("this `async fn` implicitly returns an `impl Future<Output = {}>`", snip),
             );
         }
-        e.emit();
+        err.emit();
         Some(ErrorReported)
     }
+
+    fn suggest_adding_lifetime_params(
+        &self,
+        sub: Region<'tcx>,
+        ty_sup: &Ty<'_>,
+        ty_sub: &Ty<'_>,
+        err: &mut DiagnosticBuilder<'_>,
+    ) {
+        if let (
+            hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. },
+            hir::Ty { kind: hir::TyKind::Rptr(lifetime_sup, _), .. },
+        ) = (ty_sub, ty_sup)
+        {
+            if lifetime_sub.name.is_elided() && lifetime_sup.name.is_elided() {
+                if let Some(anon_reg) = self.tcx().is_suitable_region(sub) {
+                    let hir_id = self.tcx().hir().local_def_id_to_hir_id(anon_reg.def_id);
+                    if let hir::Node::Item(&hir::Item {
+                        kind: hir::ItemKind::Fn(_, ref generics, ..),
+                        ..
+                    }) = self.tcx().hir().get(hir_id)
+                    {
+                        let (suggestion_param_name, introduce_new) = generics
+                            .params
+                            .iter()
+                            .find(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
+                            .and_then(|p| self.tcx().sess.source_map().span_to_snippet(p.span).ok())
+                            .map(|name| (name, false))
+                            .unwrap_or_else(|| ("'a".to_string(), true));
+
+                        let mut suggestions = vec![
+                            if let hir::LifetimeName::Underscore = lifetime_sub.name {
+                                (lifetime_sub.span, suggestion_param_name.clone())
+                            } else {
+                                (
+                                    lifetime_sub.span.shrink_to_hi(),
+                                    suggestion_param_name.clone() + " ",
+                                )
+                            },
+                            if let hir::LifetimeName::Underscore = lifetime_sup.name {
+                                (lifetime_sup.span, suggestion_param_name.clone())
+                            } else {
+                                (
+                                    lifetime_sup.span.shrink_to_hi(),
+                                    suggestion_param_name.clone() + " ",
+                                )
+                            },
+                        ];
+
+                        if introduce_new {
+                            let new_param_suggestion = match &generics.params {
+                                [] => (generics.span, format!("<{}>", suggestion_param_name)),
+                                [first, ..] => (
+                                    first.span.shrink_to_lo(),
+                                    format!("{}, ", suggestion_param_name),
+                                ),
+                            };
+
+                            suggestions.push(new_param_suggestion);
+                        }
+
+                        err.multipart_suggestion(
+                            "consider introducing a named lifetime parameter",
+                            suggestions,
+                            Applicability::MaybeIncorrect,
+                        );
+                        err.note(
+                            "each elided lifetime in input position becomes a distinct lifetime",
+                        );
+                    }
+                }
+            }
+        }
+    }
 }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 6b905f67e68..9dae978dcde 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1252,16 +1252,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         self.tainted_by_errors_flag.set(true)
     }
 
-    /// Process the region constraints and report any errors that
+    /// Process the region constraints and return any any errors that
     /// result. After this, no more unification operations should be
     /// done -- or the compiler will panic -- but it is legal to use
     /// `resolve_vars_if_possible` as well as `fully_resolve`.
-    pub fn resolve_regions_and_report_errors(
+    pub fn resolve_regions(
         &self,
         region_context: DefId,
         outlives_env: &OutlivesEnvironment<'tcx>,
         mode: RegionckMode,
-    ) {
+    ) -> Vec<RegionResolutionError<'tcx>> {
         let (var_infos, data) = {
             let mut inner = self.inner.borrow_mut();
             let inner = &mut *inner;
@@ -1287,6 +1287,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
         assert!(old_value.is_none());
 
+        errors
+    }
+
+    /// Process the region constraints and report any errors that
+    /// result. After this, no more unification operations should be
+    /// done -- or the compiler will panic -- but it is legal to use
+    /// `resolve_vars_if_possible` as well as `fully_resolve`.
+    pub fn resolve_regions_and_report_errors(
+        &self,
+        region_context: DefId,
+        outlives_env: &OutlivesEnvironment<'tcx>,
+        mode: RegionckMode,
+    ) {
+        let errors = self.resolve_regions(region_context, outlives_env, mode);
+
         if !self.is_tainted_by_errors() {
             // As a heuristic, just skip reporting region errors
             // altogether if other errors have been reported while
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 6fd0a5b95f9..4c936dec6f2 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -16,9 +16,9 @@
 
 use self::TargetLint::*;
 
-use crate::hidden_unicode_codepoints::UNICODE_TEXT_FLOW_CHARS;
 use crate::levels::{is_known_lint_tool, LintLevelsBuilder};
 use crate::passes::{EarlyLintPassObject, LateLintPassObject};
+use ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync;
@@ -602,7 +602,7 @@ pub trait LintContext: Sized {
                     let spans: Vec<_> = content
                         .char_indices()
                         .filter_map(|(i, c)| {
-                            UNICODE_TEXT_FLOW_CHARS.contains(&c).then(|| {
+                            TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
                                 let lo = span.lo() + BytePos(2 + i as u32);
                                 (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
                             })
diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
index 1bcdcb806fc..fde84be9a7c 100644
--- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
+++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
@@ -1,4 +1,5 @@
 use crate::{EarlyContext, EarlyLintPass, LintContext};
+use ast::util::unicode::{contains_text_flow_control_chars, TEXT_FLOW_CONTROL_CHARS};
 use rustc_ast as ast;
 use rustc_errors::{Applicability, SuggestionStyle};
 use rustc_span::{BytePos, Span, Symbol};
@@ -37,11 +38,6 @@ declare_lint! {
 
 declare_lint_pass!(HiddenUnicodeCodepoints => [TEXT_DIRECTION_CODEPOINT_IN_LITERAL]);
 
-crate const UNICODE_TEXT_FLOW_CHARS: &[char] = &[
-    '\u{202A}', '\u{202B}', '\u{202D}', '\u{202E}', '\u{2066}', '\u{2067}', '\u{2068}', '\u{202C}',
-    '\u{2069}',
-];
-
 impl HiddenUnicodeCodepoints {
     fn lint_text_direction_codepoint(
         &self,
@@ -57,7 +53,7 @@ impl HiddenUnicodeCodepoints {
             .as_str()
             .char_indices()
             .filter_map(|(i, c)| {
-                UNICODE_TEXT_FLOW_CHARS.contains(&c).then(|| {
+                TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
                     let lo = span.lo() + BytePos(i as u32 + padding);
                     (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
                 })
@@ -131,7 +127,7 @@ impl HiddenUnicodeCodepoints {
 impl EarlyLintPass for HiddenUnicodeCodepoints {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
         if let ast::AttrKind::DocComment(_, comment) = attr.kind {
-            if comment.as_str().contains(UNICODE_TEXT_FLOW_CHARS) {
+            if contains_text_flow_control_chars(&comment.as_str()) {
                 self.lint_text_direction_codepoint(cx, comment, attr.span, 0, false, "doc comment");
             }
         }
@@ -142,7 +138,7 @@ impl EarlyLintPass for HiddenUnicodeCodepoints {
         let (text, span, padding) = match &expr.kind {
             ast::ExprKind::Lit(ast::Lit { token, kind, span }) => {
                 let text = token.symbol;
-                if !text.as_str().contains(UNICODE_TEXT_FLOW_CHARS) {
+                if !contains_text_flow_control_chars(&text.as_str()) {
                     return;
                 }
                 let padding = match kind {
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index b83d04f3dc2..c1a53c34b7a 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3054,6 +3054,7 @@ declare_lint_pass! {
         BREAK_WITH_LABEL_AND_LOOP,
         UNUSED_ATTRIBUTES,
         NON_EXHAUSTIVE_OMITTED_PATTERNS,
+        TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
         DEREF_INTO_DYN_SUPERTRAIT,
     ]
 }
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 32b866e81b1..ddbc3c59128 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -75,6 +75,10 @@ extern "C" void LLVMTimeTraceProfilerInitialize() {
       /* ProcName */ "rustc");
 }
 
+extern "C" void LLVMTimeTraceProfilerFinishThread() {
+  timeTraceProfilerFinishThread();
+}
+
 extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
   StringRef FN(FileName);
   std::error_code EC;
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index bbd30c9327a..8db2291dfcf 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -236,7 +236,7 @@ use std::fmt::Write as _;
 use std::io::{Read, Result as IoResult, Write};
 use std::path::{Path, PathBuf};
 use std::{cmp, fmt, fs};
-use tracing::{debug, info, warn};
+use tracing::{debug, info};
 
 #[derive(Clone)]
 crate struct CrateLocator<'a> {
@@ -549,7 +549,7 @@ impl<'a> CrateLocator<'a> {
                         }
                     }
                     Err(err) => {
-                        warn!("no metadata found: {}", err);
+                        info!("no metadata found: {}", err);
                         continue;
                     }
                 };
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 42683dac426..1260c691e78 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -632,11 +632,11 @@ fn tooltip<'tcx>(
     for statement in statements {
         let source_range = source_range_no_file(tcx, &statement.source_info.span);
         text.push(format!(
-            "\n{}{}: {}: {}",
+            "\n{}{}: {}: {:?}",
             TOOLTIP_INDENT,
             source_range,
             statement_kind_name(&statement),
-            format!("{:?}", statement)
+            statement
         ));
     }
     if let Some(term) = terminator {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 8ec5f4c7978..b87e23af72b 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -3060,9 +3060,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                     // LLVM's definition of `noalias` is based solely on memory
                     // dependencies rather than pointer equality
                     //
-                    // Due to miscompiles in LLVM < 12, we apply a separate NoAliasMutRef attribute
-                    // for UniqueBorrowed arguments, so that the codegen backend can decide
-                    // whether or not to actually emit the attribute.
+                    // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute
+                    // for UniqueBorrowed arguments, so that the codegen backend can decide whether
+                    // or not to actually emit the attribute. It can also be controlled with the
+                    // `-Zmutable-noalias` debugging option.
                     let no_alias = match kind {
                         PointerKind::Shared | PointerKind::UniqueBorrowed => false,
                         PointerKind::UniqueOwned => true,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index b11a54d5dcb..742005e245f 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -744,6 +744,7 @@ pub trait PrettyPrinter<'tcx>:
                     p!(print_def_path(did, substs));
                     if !substs.as_closure().is_valid() {
                         p!(" closure_substs=(unavailable)");
+                        p!(write(" substs={:?}", substs));
                     } else {
                         p!(" closure_kind_ty=", print(substs.as_closure().kind_ty()));
                         p!(
diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
index 158ba1b9425..d38b567a958 100644
--- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
@@ -3,25 +3,14 @@ use super::*;
 use crate::{AnalysisDomain, GenKill, GenKillAnalysis};
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{ParamEnv, TyCtxt};
-use rustc_span::DUMMY_SP;
-
-pub type MaybeMutBorrowedLocals<'mir, 'tcx> = MaybeBorrowedLocals<MutBorrow<'mir, 'tcx>>;
 
 /// A dataflow analysis that tracks whether a pointer or reference could possibly exist that points
 /// to a given local.
 ///
-/// The `K` parameter determines what kind of borrows are tracked. By default,
-/// `MaybeBorrowedLocals` looks for *any* borrow of a local. If you are only interested in borrows
-/// that might allow mutation, use the `MaybeMutBorrowedLocals` type alias instead.
-///
 /// At present, this is used as a very limited form of alias analysis. For example,
 /// `MaybeBorrowedLocals` is used to compute which locals are live during a yield expression for
-/// immovable generators. `MaybeMutBorrowedLocals` is used during const checking to prove that a
-/// local has not been mutated via indirect assignment (e.g., `*p = 42`), the side-effects of a
-/// function call or inline assembly.
-pub struct MaybeBorrowedLocals<K = AnyBorrow> {
-    kind: K,
+/// immovable generators.
+pub struct MaybeBorrowedLocals {
     ignore_borrow_on_drop: bool,
 }
 
@@ -29,29 +18,11 @@ impl MaybeBorrowedLocals {
     /// A dataflow analysis that records whether a pointer or reference exists that may alias the
     /// given local.
     pub fn all_borrows() -> Self {
-        MaybeBorrowedLocals { kind: AnyBorrow, ignore_borrow_on_drop: false }
-    }
-}
-
-impl MaybeMutBorrowedLocals<'mir, 'tcx> {
-    /// A dataflow analysis that records whether a pointer or reference exists that may *mutably*
-    /// alias the given local.
-    ///
-    /// This includes `&mut` and pointers derived from an `&mut`, as well as shared borrows of
-    /// types with interior mutability.
-    pub fn mut_borrows_only(
-        tcx: TyCtxt<'tcx>,
-        body: &'mir mir::Body<'tcx>,
-        param_env: ParamEnv<'tcx>,
-    ) -> Self {
-        MaybeBorrowedLocals {
-            kind: MutBorrow { body, tcx, param_env },
-            ignore_borrow_on_drop: false,
-        }
+        MaybeBorrowedLocals { ignore_borrow_on_drop: false }
     }
 }
 
-impl<K> MaybeBorrowedLocals<K> {
+impl MaybeBorrowedLocals {
     /// During dataflow analysis, ignore the borrow that may occur when a place is dropped.
     ///
     /// Drop terminators may call custom drop glue (`Drop::drop`), which takes `&mut self` as a
@@ -69,21 +40,14 @@ impl<K> MaybeBorrowedLocals<K> {
         MaybeBorrowedLocals { ignore_borrow_on_drop: true, ..self }
     }
 
-    fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T, K> {
-        TransferFunction {
-            kind: &self.kind,
-            trans,
-            ignore_borrow_on_drop: self.ignore_borrow_on_drop,
-        }
+    fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T> {
+        TransferFunction { trans, ignore_borrow_on_drop: self.ignore_borrow_on_drop }
     }
 }
 
-impl<K> AnalysisDomain<'tcx> for MaybeBorrowedLocals<K>
-where
-    K: BorrowAnalysisKind<'tcx>,
-{
+impl AnalysisDomain<'tcx> for MaybeBorrowedLocals {
     type Domain = BitSet<Local>;
-    const NAME: &'static str = K::ANALYSIS_NAME;
+    const NAME: &'static str = "maybe_borrowed_locals";
 
     fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
         // bottom = unborrowed
@@ -95,10 +59,7 @@ where
     }
 }
 
-impl<K> GenKillAnalysis<'tcx> for MaybeBorrowedLocals<K>
-where
-    K: BorrowAnalysisKind<'tcx>,
-{
+impl GenKillAnalysis<'tcx> for MaybeBorrowedLocals {
     type Idx = Local;
 
     fn statement_effect(
@@ -131,16 +92,14 @@ where
 }
 
 /// A `Visitor` that defines the transfer function for `MaybeBorrowedLocals`.
-struct TransferFunction<'a, T, K> {
+struct TransferFunction<'a, T> {
     trans: &'a mut T,
-    kind: &'a K,
     ignore_borrow_on_drop: bool,
 }
 
-impl<T, K> Visitor<'tcx> for TransferFunction<'a, T, K>
+impl<T> Visitor<'tcx> for TransferFunction<'a, T>
 where
     T: GenKill<Local>,
-    K: BorrowAnalysisKind<'tcx>,
 {
     fn visit_statement(&mut self, stmt: &Statement<'tcx>, location: Location) {
         self.super_statement(stmt, location);
@@ -156,14 +115,14 @@ where
         self.super_rvalue(rvalue, location);
 
         match rvalue {
-            mir::Rvalue::AddressOf(mt, borrowed_place) => {
-                if !borrowed_place.is_indirect() && self.kind.in_address_of(*mt, *borrowed_place) {
+            mir::Rvalue::AddressOf(_mt, borrowed_place) => {
+                if !borrowed_place.is_indirect() {
                     self.trans.gen(borrowed_place.local);
                 }
             }
 
-            mir::Rvalue::Ref(_, kind, borrowed_place) => {
-                if !borrowed_place.is_indirect() && self.kind.in_ref(*kind, *borrowed_place) {
+            mir::Rvalue::Ref(_, _kind, borrowed_place) => {
+                if !borrowed_place.is_indirect() {
                     self.trans.gen(borrowed_place.local);
                 }
             }
@@ -211,64 +170,3 @@ where
         }
     }
 }
-
-pub struct AnyBorrow;
-
-pub struct MutBorrow<'mir, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    body: &'mir Body<'tcx>,
-    param_env: ParamEnv<'tcx>,
-}
-
-impl MutBorrow<'mir, 'tcx> {
-    /// `&` and `&raw` only allow mutation if the borrowed place is `!Freeze`.
-    ///
-    /// This assumes that it is UB to take the address of a struct field whose type is
-    /// `Freeze`, then use pointer arithmetic to derive a pointer to a *different* field of
-    /// that same struct whose type is `!Freeze`. If we decide that this is not UB, we will
-    /// have to check the type of the borrowed **local** instead of the borrowed **place**
-    /// below. See [rust-lang/unsafe-code-guidelines#134].
-    ///
-    /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
-    fn shared_borrow_allows_mutation(&self, place: Place<'tcx>) -> bool {
-        !place.ty(self.body, self.tcx).ty.is_freeze(self.tcx.at(DUMMY_SP), self.param_env)
-    }
-}
-
-pub trait BorrowAnalysisKind<'tcx> {
-    const ANALYSIS_NAME: &'static str;
-
-    fn in_address_of(&self, mt: Mutability, place: Place<'tcx>) -> bool;
-    fn in_ref(&self, kind: mir::BorrowKind, place: Place<'tcx>) -> bool;
-}
-
-impl BorrowAnalysisKind<'tcx> for AnyBorrow {
-    const ANALYSIS_NAME: &'static str = "maybe_borrowed_locals";
-
-    fn in_ref(&self, _: mir::BorrowKind, _: Place<'_>) -> bool {
-        true
-    }
-    fn in_address_of(&self, _: Mutability, _: Place<'_>) -> bool {
-        true
-    }
-}
-
-impl BorrowAnalysisKind<'tcx> for MutBorrow<'mir, 'tcx> {
-    const ANALYSIS_NAME: &'static str = "maybe_mut_borrowed_locals";
-
-    fn in_ref(&self, kind: mir::BorrowKind, place: Place<'tcx>) -> bool {
-        match kind {
-            mir::BorrowKind::Mut { .. } => true,
-            mir::BorrowKind::Shared | mir::BorrowKind::Shallow | mir::BorrowKind::Unique => {
-                self.shared_borrow_allows_mutation(place)
-            }
-        }
-    }
-
-    fn in_address_of(&self, mt: Mutability, place: Place<'tcx>) -> bool {
-        match mt {
-            Mutability::Mut => true,
-            Mutability::Not => self.shared_borrow_allows_mutation(place),
-        }
-    }
-}
diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs
index 474f4f2a79b..91dddc6cd55 100644
--- a/compiler/rustc_mir_dataflow/src/impls/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs
@@ -22,7 +22,7 @@ mod init_locals;
 mod liveness;
 mod storage_liveness;
 
-pub use self::borrowed_locals::{MaybeBorrowedLocals, MaybeMutBorrowedLocals};
+pub use self::borrowed_locals::MaybeBorrowedLocals;
 pub use self::init_locals::MaybeInitializedLocals;
 pub use self::liveness::MaybeLiveLocals;
 pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageLive};
diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
index 2d27d085b48..28e5d76783a 100644
--- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs
+++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
@@ -11,8 +11,7 @@ use rustc_middle::mir::{self, Body, Local, Location};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
 use crate::impls::{
-    DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeMutBorrowedLocals,
-    MaybeUninitializedPlaces,
+    DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeUninitializedPlaces,
 };
 use crate::move_paths::{HasMoveData, MoveData};
 use crate::move_paths::{LookupResult, MovePathIndex};
@@ -62,14 +61,6 @@ impl<'tcx> MirPass<'tcx> for SanityCheck {
             sanity_check_via_rustc_peek(tcx, body, &attributes, &flow_def_inits);
         }
 
-        if has_rustc_mir_with(sess, &attributes, sym::rustc_peek_indirectly_mutable).is_some() {
-            let flow_mut_borrowed = MaybeMutBorrowedLocals::mut_borrows_only(tcx, body, param_env)
-                .into_engine(tcx, body)
-                .iterate_to_fixpoint();
-
-            sanity_check_via_rustc_peek(tcx, body, &attributes, &flow_mut_borrowed);
-        }
-
         if has_rustc_mir_with(sess, &attributes, sym::rustc_peek_liveness).is_some() {
             let flow_liveness = MaybeLiveLocals.into_engine(tcx, body).iterate_to_fixpoint();
 
@@ -281,26 +272,6 @@ where
     }
 }
 
-impl<'tcx> RustcPeekAt<'tcx> for MaybeMutBorrowedLocals<'_, 'tcx> {
-    fn peek_at(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        place: mir::Place<'tcx>,
-        flow_state: &BitSet<Local>,
-        call: PeekCall,
-    ) {
-        info!(?place, "peek_at");
-        let Some(local) = place.as_local() else {
-            tcx.sess.span_err(call.span, "rustc_peek: argument was not a local");
-            return;
-        };
-
-        if !flow_state.contains(local) {
-            tcx.sess.span_err(call.span, "rustc_peek: bit not set");
-        }
-    }
-}
-
 impl<'tcx> RustcPeekAt<'tcx> for MaybeLiveLocals {
     fn peek_at(
         &self,
diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs
index 799b4e18c24..4392c02f874 100644
--- a/compiler/rustc_monomorphize/src/util.rs
+++ b/compiler/rustc_monomorphize/src/util.rs
@@ -67,7 +67,7 @@ crate fn dump_closure_profile(tcx: TyCtxt<'tcx>, closure_instance: Instance<'tcx
             src_file.prefer_local(),
             line_nos
         ) {
-            eprintln!("Error writting to file {}", e.to_string())
+            eprintln!("Error writing to file {}", e)
         }
     }
 }
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 09a3d1b9028..cf35c3cd53b 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -1,6 +1,7 @@
 use rustc_ast::ast::{self, AttrStyle};
 use rustc_ast::token::{self, CommentKind, Token, TokenKind};
 use rustc_ast::tokenstream::{Spacing, TokenStream};
+use rustc_ast::util::unicode::contains_text_flow_control_chars;
 use rustc_errors::{error_code, Applicability, DiagnosticBuilder, FatalError, PResult};
 use rustc_lexer::unescape::{self, Mode};
 use rustc_lexer::{Base, DocStyle, RawStrError};
@@ -137,12 +138,8 @@ impl<'a> StringReader<'a> {
         // Opening delimiter of the length 2 is not included into the comment text.
         let content_start = start + BytePos(2);
         let content = self.str_from(content_start);
-        let span = self.mk_sp(start, self.pos);
-        const UNICODE_TEXT_FLOW_CHARS: &[char] = &[
-            '\u{202A}', '\u{202B}', '\u{202D}', '\u{202E}', '\u{2066}', '\u{2067}', '\u{2068}',
-            '\u{202C}', '\u{2069}',
-        ];
-        if content.contains(UNICODE_TEXT_FLOW_CHARS) {
+        if contains_text_flow_control_chars(content) {
+            let span = self.mk_sp(start, self.pos);
             self.sess.buffer_lint_with_diagnostic(
                 &TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
                 span,
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 163acebccea..ff0d76e94fd 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -420,6 +420,10 @@ impl<'a> Resolver<'a> {
                 err.span_label(span, label);
 
                 if let Some((suggestions, msg, applicability)) = suggestion {
+                    if suggestions.is_empty() {
+                        err.help(&msg);
+                        return err;
+                    }
                     err.multipart_suggestion(&msg, suggestions, applicability);
                 }
 
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 23eb2d1aebb..5f3620b247e 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -2523,19 +2523,29 @@ impl<'a> Resolver<'a> {
                         } else {
                             (
                                 format!("use of undeclared crate or module `{}`", ident),
-                                self.find_similarly_named_module_or_crate(
-                                    ident.name,
-                                    &parent_scope.module,
-                                )
-                                .map(|sugg| {
-                                    (
-                                        vec![(ident.span, sugg.to_string())],
+                                if ident.name == sym::alloc {
+                                    Some((
+                                        vec![],
                                         String::from(
-                                            "there is a crate or module with a similar name",
+                                            "add `extern crate alloc` to use the `alloc` crate",
                                         ),
                                         Applicability::MaybeIncorrect,
+                                    ))
+                                } else {
+                                    self.find_similarly_named_module_or_crate(
+                                        ident.name,
+                                        &parent_scope.module,
                                     )
-                                }),
+                                    .map(|sugg| {
+                                        (
+                                            vec![(ident.span, sugg.to_string())],
+                                            String::from(
+                                                "there is a crate or module with a similar name",
+                                            ),
+                                            Applicability::MaybeIncorrect,
+                                        )
+                                    })
+                                },
                             )
                         }
                     } else {
diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs
index f4567b33483..f1a5282b088 100644
--- a/compiler/rustc_save_analysis/src/dump_visitor.rs
+++ b/compiler/rustc_save_analysis/src/dump_visitor.rs
@@ -236,7 +236,7 @@ impl<'tcx> DumpVisitor<'tcx> {
                             id,
                             span,
                             name: ident.to_string(),
-                            qualname: format!("{}::{}", qualname, ident.to_string()),
+                            qualname: format!("{}::{}", qualname, ident),
                             value: typ,
                             parent: None,
                             children: vec![],
@@ -889,7 +889,7 @@ impl<'tcx> DumpVisitor<'tcx> {
 
                     // Rust uses the id of the pattern for var lookups, so we'll use it too.
                     if !self.span.filter_generated(ident.span) {
-                        let qualname = format!("{}${}", ident.to_string(), hir_id);
+                        let qualname = format!("{}${}", ident, hir_id);
                         let id = id_from_hir_id(hir_id, &self.save_ctxt);
                         let span = self.span_from_span(ident.span);
 
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index e894e46a301..3add3e86148 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1193,7 +1193,7 @@ options! {
     move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED],
         "the size at which the `large_assignments` lint starts to be emitted"),
     mutable_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED],
-        "emit noalias metadata for mutable references (default: yes for LLVM >= 12, otherwise no)"),
+        "emit noalias metadata for mutable references (default: yes)"),
     new_llvm_pass_manager: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "use new LLVM pass manager (default: no)"),
     nll_facts: bool = (false, parse_bool, [UNTRACKED],
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 1b431589632..52e2a8f48e2 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -549,6 +549,7 @@ symbols! {
         div_assign,
         doc,
         doc_alias,
+        doc_auto_cfg,
         doc_cfg,
         doc_cfg_hide,
         doc_keyword,
@@ -1127,7 +1128,6 @@ symbols! {
         rustc_partition_reused,
         rustc_peek,
         rustc_peek_definite_init,
-        rustc_peek_indirectly_mutable,
         rustc_peek_liveness,
         rustc_peek_maybe_init,
         rustc_peek_maybe_uninit,
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index d9eb299e2fd..4768c9e2db5 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -68,8 +68,10 @@ mod attr_impl {
             const NonNull   = 1 << 3;
             const ReadOnly  = 1 << 4;
             const InReg     = 1 << 5;
-            // NoAlias on &mut arguments can only be used with LLVM >= 12 due to miscompiles
-            // in earlier versions. FIXME: Remove this distinction once possible.
+            // Due to past miscompiles in LLVM, we use a separate attribute for
+            // &mut arguments, so that the codegen backend can decide whether
+            // or not to actually emit the attribute. It can also be controlled
+            // with the `-Zmutable-noalias` debugging option.
             const NoAliasMutRef = 1 << 6;
         }
     }
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
index 2c71fb8afee..ca3550e9278 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
@@ -2,7 +2,7 @@ use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, Target, TargetOption
 
 pub fn target() -> Target {
     let mut base = super::apple_base::opts("macos");
-    base.cpu = "apple-a12".to_string();
+    base.cpu = "apple-a14".to_string();
     base.max_atomic_width = Some(128);
 
     // FIXME: The leak sanitizer currently fails the tests, see #88132.
diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
index 71ee6deb07f..a393858879b 100644
--- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         options: TargetOptions {
+            features: "+outline-atomics".to_string(),
             max_atomic_width: Some(128),
             mcount: "\u{1}_mcount".to_string(),
             endian: Endian::Big,
diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
index e05360ea45c..e75100f1435 100644
--- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
         arch: "aarch64".to_string(),
         options: TargetOptions {
             abi: "ilp32".to_string(),
+            features: "+outline-atomics".to_string(),
             mcount: "\u{1}_mcount".to_string(),
             endian: Endian::Big,
             ..base
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
index c8d46adbfd9..850381f7fb0 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
@@ -7,6 +7,7 @@ pub fn target() -> Target {
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         options: TargetOptions {
+            features: "+outline-atomics".to_string(),
             mcount: "\u{1}_mcount".to_string(),
             max_atomic_width: Some(128),
             supported_sanitizers: SanitizerSet::ADDRESS
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
index 8522405f61f..1c931d5a705 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
         arch: "aarch64".to_string(),
         options: TargetOptions {
             abi: "ilp32".to_string(),
+            features: "+outline-atomics".to_string(),
             max_atomic_width: Some(128),
             mcount: "\u{1}_mcount".to_string(),
             ..super::linux_gnu_base::opts()
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
index 6a16b4ce419..0770f3496c2 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
@@ -9,6 +9,10 @@ pub fn target() -> Target {
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
-        options: TargetOptions { mcount: "\u{1}_mcount".to_string(), ..base },
+        options: TargetOptions {
+            features: "+outline-atomics".to_string(),
+            mcount: "\u{1}_mcount".to_string(),
+            ..base
+        },
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 5d17693dc08..a9125b9fd22 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1838,7 +1838,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
                 post.iter().map(|p| format!("- {}", p)).take(4).collect::<Vec<_>>().join("\n"),
                 post.len() - 4,
             )
-        } else if post.len() > 1 || (post.len() == 1 && post[0].contains("\n")) {
+        } else if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
             format!(":\n{}", post.iter().map(|p| format!("- {}", p)).collect::<Vec<_>>().join("\n"),)
         } else if post.len() == 1 {
             format!(": `{}`", post[0])
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 428873b8d3d..8f247184e88 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -748,6 +748,9 @@ fn vtable_trait_first_method_offset<'tcx>(
 ) -> usize {
     let (trait_to_be_found, trait_owning_vtable) = key;
 
+    // #90177
+    let trait_to_be_found_erased = tcx.erase_regions(trait_to_be_found);
+
     let vtable_segment_callback = {
         let mut vtable_base = 0;
 
@@ -757,7 +760,7 @@ fn vtable_trait_first_method_offset<'tcx>(
                     vtable_base += COMMON_VTABLE_ENTRIES.len();
                 }
                 VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
-                    if trait_ref == trait_to_be_found {
+                    if tcx.erase_regions(trait_ref) == trait_to_be_found_erased {
                         return ControlFlow::Break(vtable_base);
                     }
                     vtable_base += util::count_own_vtable_entries(tcx, trait_ref);
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index db8a6d96204..b8c66931cbe 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1734,7 +1734,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
         ty: ret_type,
     });
 
-    confirm_param_env_candidate(selcx, obligation, predicate, false)
+    confirm_param_env_candidate(selcx, obligation, predicate, true)
 }
 
 fn confirm_param_env_candidate<'cx, 'tcx>(
@@ -1754,8 +1754,18 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
     );
 
     let cache_projection = cache_entry.projection_ty;
-    let obligation_projection = obligation.predicate;
     let mut nested_obligations = Vec::new();
+    let obligation_projection = obligation.predicate;
+    let obligation_projection = ensure_sufficient_stack(|| {
+        normalize_with_depth_to(
+            selcx,
+            obligation.param_env,
+            obligation.cause.clone(),
+            obligation.recursion_depth + 1,
+            obligation_projection,
+            &mut nested_obligations,
+        )
+    });
     let cache_projection = if potentially_unnormalized_candidate {
         ensure_sufficient_stack(|| {
             normalize_with_depth_to(
@@ -1771,6 +1781,8 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
         cache_projection
     };
 
+    debug!(?cache_projection, ?obligation_projection);
+
     match infcx.at(cause, param_env).eq(cache_projection, obligation_projection) {
         Ok(InferOk { value: _, obligations }) => {
             nested_obligations.extend(obligations);
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 84721922c8d..2f1f7971a79 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -620,23 +620,37 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             _ => bug!("closure candidate for non-closure {:?}", obligation),
         };
 
+        let obligation_predicate = obligation.predicate.to_poly_trait_ref();
+        let Normalized { value: obligation_predicate, mut obligations } =
+            ensure_sufficient_stack(|| {
+                normalize_with_depth(
+                    self,
+                    obligation.param_env,
+                    obligation.cause.clone(),
+                    obligation.recursion_depth + 1,
+                    obligation_predicate,
+                )
+            });
+
         let trait_ref = self.closure_trait_ref_unnormalized(obligation, substs);
-        let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| {
-            normalize_with_depth(
-                self,
-                obligation.param_env,
-                obligation.cause.clone(),
-                obligation.recursion_depth + 1,
-                trait_ref,
-            )
-        });
+        let Normalized { value: trait_ref, obligations: trait_ref_obligations } =
+            ensure_sufficient_stack(|| {
+                normalize_with_depth(
+                    self,
+                    obligation.param_env,
+                    obligation.cause.clone(),
+                    obligation.recursion_depth + 1,
+                    trait_ref,
+                )
+            });
 
         debug!(?closure_def_id, ?trait_ref, ?obligations, "confirm closure candidate obligations");
 
+        obligations.extend(trait_ref_obligations);
         obligations.extend(self.confirm_poly_trait_refs(
             obligation.cause.clone(),
             obligation.param_env,
-            obligation.predicate.to_poly_trait_ref(),
+            obligation_predicate,
             trait_ref,
         )?);
 
@@ -948,52 +962,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 let tail_field_ty = tcx.type_of(tail_field.did);
 
                 let mut unsizing_params = GrowableBitSet::new_empty();
-                if tcx.features().relaxed_struct_unsize {
-                    for arg in tail_field_ty.walk(tcx) {
-                        if let Some(i) = maybe_unsizing_param_idx(arg) {
-                            unsizing_params.insert(i);
-                        }
-                    }
-
-                    // Ensure none of the other fields mention the parameters used
-                    // in unsizing.
-                    for field in prefix_fields {
-                        for arg in tcx.type_of(field.did).walk(tcx) {
-                            if let Some(i) = maybe_unsizing_param_idx(arg) {
-                                unsizing_params.remove(i);
-                            }
-                        }
+                for arg in tail_field_ty.walk(tcx) {
+                    if let Some(i) = maybe_unsizing_param_idx(arg) {
+                        unsizing_params.insert(i);
                     }
+                }
 
-                    if unsizing_params.is_empty() {
-                        return Err(Unimplemented);
-                    }
-                } else {
-                    let mut found = false;
-                    for arg in tail_field_ty.walk(tcx) {
+                // Ensure none of the other fields mention the parameters used
+                // in unsizing.
+                for field in prefix_fields {
+                    for arg in tcx.type_of(field.did).walk(tcx) {
                         if let Some(i) = maybe_unsizing_param_idx(arg) {
-                            unsizing_params.insert(i);
-                            found = true;
+                            unsizing_params.remove(i);
                         }
                     }
-                    if !found {
-                        return Err(Unimplemented);
-                    }
+                }
 
-                    // Ensure none of the other fields mention the parameters used
-                    // in unsizing.
-                    // FIXME(eddyb) cache this (including computing `unsizing_params`)
-                    // by putting it in a query; it would only need the `DefId` as it
-                    // looks at declared field types, not anything substituted.
-                    for field in prefix_fields {
-                        for arg in tcx.type_of(field.did).walk(tcx) {
-                            if let Some(i) = maybe_unsizing_param_idx(arg) {
-                                if unsizing_params.contains(i) {
-                                    return Err(Unimplemented);
-                                }
-                            }
-                        }
-                    }
+                if unsizing_params.is_empty() {
+                    return Err(Unimplemented);
                 }
 
                 // Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`.
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs
index 5befe44802f..84327a2880e 100644
--- a/compiler/rustc_typeck/src/astconv/generics.rs
+++ b/compiler/rustc_typeck/src/astconv/generics.rs
@@ -344,7 +344,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                             "reorder the arguments: {}: `<{}>`",
                                             param_types_present
                                                 .into_iter()
-                                                .map(|ord| format!("{}s", ord.to_string()))
+                                                .map(|ord| format!("{}s", ord))
                                                 .collect::<Vec<String>>()
                                                 .join(", then "),
                                             ordered_params
diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs
index 230a576046a..86d4e4d2b11 100644
--- a/compiler/rustc_typeck/src/check/regionck.rs
+++ b/compiler/rustc_typeck/src/check/regionck.rs
@@ -103,7 +103,7 @@ macro_rules! ignore_err {
     };
 }
 
-trait OutlivesEnvironmentExt<'tcx> {
+pub(crate) trait OutlivesEnvironmentExt<'tcx> {
     fn add_implied_bounds(
         &mut self,
         infcx: &InferCtxt<'a, 'tcx>,
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs
index 9c7b0b2cacb..774d8078e52 100644
--- a/compiler/rustc_typeck/src/check/upvar.rs
+++ b/compiler/rustc_typeck/src/check/upvar.rs
@@ -86,18 +86,55 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 /// Intermediate format to store the hir_id pointing to the use that resulted in the
 /// corresponding place being captured and a String which contains the captured value's
 /// name (i.e: a.b.c)
-type CapturesInfo = (Option<hir::HirId>, String);
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+enum UpvarMigrationInfo {
+    /// We previously captured all of `x`, but now we capture some sub-path.
+    CapturingPrecise { source_expr: Option<hir::HirId>, var_name: String },
+    CapturingNothing {
+        // where the variable appears in the closure (but is not captured)
+        use_span: Span,
+    },
+}
+
+/// Reasons that we might issue a migration warning.
+#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+struct MigrationWarningReason {
+    /// When we used to capture `x` in its entirety, we implemented the auto-trait(s)
+    /// in this vec, but now we don't.
+    auto_traits: Vec<&'static str>,
+
+    /// When we used to capture `x` in its entirety, we would execute some destructors
+    /// at a different time.
+    drop_order: bool,
+}
+
+impl MigrationWarningReason {
+    fn migration_message(&self) -> String {
+        let base = "changes to closure capture in Rust 2021 will affect";
+        if !self.auto_traits.is_empty() && self.drop_order {
+            format!("{} drop order and which traits the closure implements", base)
+        } else if self.drop_order {
+            format!("{} drop order", base)
+        } else {
+            format!("{} which traits the closure implements", base)
+        }
+    }
+}
 
-/// Intermediate format to store information needed to generate migration lint. The tuple
-/// contains the hir_id pointing to the use that resulted in the
-/// corresponding place being captured, a String which contains the captured value's
-/// name (i.e: a.b.c) and a String which contains the reason why migration is needed for that
-/// capture
-type MigrationNeededForCapture = (Option<hir::HirId>, String, String);
+/// Intermediate format to store information needed to generate a note in the migration lint.
+struct MigrationLintNote {
+    captures_info: UpvarMigrationInfo,
+
+    /// reasons why migration is needed for this capture
+    reason: MigrationWarningReason,
+}
 
 /// Intermediate format to store the hir id of the root variable and a HashSet containing
 /// information on why the root variable should be fully captured
-type MigrationDiagnosticInfo = (hir::HirId, Vec<MigrationNeededForCapture>);
+struct NeededMigration {
+    var_hir_id: hir::HirId,
+    diagnostics_info: Vec<MigrationLintNote>,
+}
 
 struct InferBorrowKindVisitor<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
@@ -707,47 +744,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                  closure_head_span,
                 |lint| {
                     let mut diagnostics_builder = lint.build(
-                        format!(
-                            "changes to closure capture in Rust 2021 will affect {}",
-                            reasons
-                        )
-                        .as_str(),
+                        &reasons.migration_message(),
                     );
-                    for (var_hir_id, diagnostics_info) in need_migrations.iter() {
+                    for NeededMigration { var_hir_id, diagnostics_info } in &need_migrations {
                         // Labels all the usage of the captured variable and why they are responsible
                         // for migration being needed
-                        for (captured_hir_id, captured_name, reasons) in diagnostics_info.iter() {
-                            if let Some(captured_hir_id) = captured_hir_id {
-                                let cause_span = self.tcx.hir().span(*captured_hir_id);
-                                diagnostics_builder.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`",
-                                    self.tcx.hir().name(*var_hir_id),
-                                    captured_name,
-                                ));
+                        for lint_note in diagnostics_info.iter() {
+                            match &lint_note.captures_info {
+                                UpvarMigrationInfo::CapturingPrecise { source_expr: Some(capture_expr_id), var_name: captured_name } => {
+                                    let cause_span = self.tcx.hir().span(*capture_expr_id);
+                                    diagnostics_builder.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`",
+                                        self.tcx.hir().name(*var_hir_id),
+                                        captured_name,
+                                    ));
+                                }
+                                UpvarMigrationInfo::CapturingNothing { use_span } => {
+                                    diagnostics_builder.span_label(*use_span, format!("in Rust 2018, this causes the closure to capture `{}`, but in Rust 2021, it has no effect",
+                                        self.tcx.hir().name(*var_hir_id),
+                                    ));
+                                }
+
+                                _ => { }
                             }
 
                             // Add a label pointing to where a captured variable affected by drop order
                             // is dropped
-                            if reasons.contains("drop order") {
+                            if lint_note.reason.drop_order {
                                 let drop_location_span = drop_location_span(self.tcx, &closure_hir_id);
 
-                                diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure",
-                                    self.tcx.hir().name(*var_hir_id),
-                                    captured_name,
-                                ));
+                                match &lint_note.captures_info {
+                                    UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
+                                        diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure",
+                                            self.tcx.hir().name(*var_hir_id),
+                                            captured_name,
+                                        ));
+                                    }
+                                    UpvarMigrationInfo::CapturingNothing { use_span: _ } => {
+                                        diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{v}` is dropped here along with the closure, but in Rust 2021 `{v}` is not part of the closure",
+                                            v = self.tcx.hir().name(*var_hir_id),
+                                        ));
+                                    }
+                                }
                             }
 
                             // Add a label explaining why a closure no longer implements a trait
-                            if reasons.contains("trait implementation") {
-                                let missing_trait = &reasons[..reasons.find("trait implementation").unwrap() - 1];
-
-                                diagnostics_builder.span_label(closure_head_span, format!("in Rust 2018, this closure implements {} as `{}` implements {}, but in Rust 2021, this closure will no longer implement {} as `{}` does not implement {}",
-                                    missing_trait,
-                                    self.tcx.hir().name(*var_hir_id),
-                                    missing_trait,
-                                    missing_trait,
-                                    captured_name,
-                                    missing_trait,
-                                ));
+                            for &missing_trait in &lint_note.reason.auto_traits {
+                                // not capturing something anymore cannot cause a trait to fail to be implemented:
+                                match &lint_note.captures_info {
+                                    UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
+                                        let var_name = self.tcx.hir().name(*var_hir_id);
+                                        diagnostics_builder.span_label(closure_head_span, format!("\
+                                        in Rust 2018, this closure implements {missing_trait} \
+                                        as `{var_name}` implements {missing_trait}, but in Rust 2021, \
+                                        this closure will no longer implement {missing_trait} \
+                                        because `{var_name}` is not fully captured \
+                                        and `{captured_name}` does not implement {missing_trait}"));
+                                    }
+
+                                    // Cannot happen: if we don't capture a variable, we impl strictly more traits
+                                    UpvarMigrationInfo::CapturingNothing { use_span } => span_bug!(*use_span, "missing trait from not capturing something"),
+                                }
                             }
                         }
                     }
@@ -840,25 +896,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Combines all the reasons for 2229 migrations
     fn compute_2229_migrations_reasons(
         &self,
-        auto_trait_reasons: FxHashSet<&str>,
-        drop_reason: bool,
-    ) -> String {
-        let mut reasons = String::new();
-
-        if !auto_trait_reasons.is_empty() {
-            reasons = format!(
-                "{} trait implementation for closure",
-                auto_trait_reasons.clone().into_iter().collect::<Vec<&str>>().join(", ")
-            );
-        }
+        auto_trait_reasons: FxHashSet<&'static str>,
+        drop_order: bool,
+    ) -> MigrationWarningReason {
+        let mut reasons = MigrationWarningReason::default();
 
-        if !auto_trait_reasons.is_empty() && drop_reason {
-            reasons = format!("{} and ", reasons);
+        for auto_trait in auto_trait_reasons {
+            reasons.auto_traits.push(auto_trait);
         }
 
-        if drop_reason {
-            reasons = format!("{}drop order", reasons);
-        }
+        reasons.drop_order = drop_order;
 
         reasons
     }
@@ -874,7 +921,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
         var_hir_id: hir::HirId,
         closure_clause: hir::CaptureBy,
-    ) -> Option<FxHashMap<CapturesInfo, FxHashSet<&str>>> {
+    ) -> Option<FxHashMap<UpvarMigrationInfo, FxHashSet<&'static str>>> {
         let auto_traits_def_id = vec![
             self.tcx.lang_items().clone_trait(),
             self.tcx.lang_items().sync_trait(),
@@ -963,7 +1010,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             if !capture_problems.is_empty() {
                 problematic_captures.insert(
-                    (capture.info.path_expr_id, capture.to_string(self.tcx)),
+                    UpvarMigrationInfo::CapturingPrecise {
+                        source_expr: capture.info.path_expr_id,
+                        var_name: capture.to_string(self.tcx),
+                    },
                     capture_problems,
                 );
             }
@@ -986,6 +1036,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ///
     /// This function only returns a HashSet of CapturesInfo for significant drops. If there
     /// are no significant drops than None is returned
+    #[instrument(level = "debug", skip(self))]
     fn compute_2229_migrations_for_drop(
         &self,
         closure_def_id: DefId,
@@ -993,25 +1044,41 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
         closure_clause: hir::CaptureBy,
         var_hir_id: hir::HirId,
-    ) -> Option<FxHashSet<CapturesInfo>> {
+    ) -> Option<FxHashSet<UpvarMigrationInfo>> {
         let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id));
 
         if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) {
+            debug!("does not have significant drop");
             return None;
         }
 
         let Some(root_var_min_capture_list) = min_captures.and_then(|m| m.get(&var_hir_id)) else {
             // The upvar is mentioned within the closure but no path starting from it is
-            // used.
+            // used. This occurs when you have (e.g.)
+            //
+            // ```
+            // let x = move || {
+            //     let _ = y;
+            // });
+            // ```
+            debug!("no path starting from it is used");
+
 
             match closure_clause {
                 // Only migrate if closure is a move closure
-                hir::CaptureBy::Value => return Some(FxHashSet::default()),
+                hir::CaptureBy::Value => {
+                    let mut diagnostics_info = FxHashSet::default();
+                    let upvars = self.tcx.upvars_mentioned(closure_def_id).expect("must be an upvar");
+                    let upvar = upvars[&var_hir_id];
+                    diagnostics_info.insert(UpvarMigrationInfo::CapturingNothing { use_span: upvar.span });
+                    return Some(diagnostics_info);
+                }
                 hir::CaptureBy::Ref => {}
             }
 
             return None;
         };
+        debug!(?root_var_min_capture_list);
 
         let mut projections_list = Vec::new();
         let mut diagnostics_info = FxHashSet::default();
@@ -1021,19 +1088,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Only care about captures that are moved into the closure
                 ty::UpvarCapture::ByValue(..) => {
                     projections_list.push(captured_place.place.projections.as_slice());
-                    diagnostics_info.insert((
-                        captured_place.info.path_expr_id,
-                        captured_place.to_string(self.tcx),
-                    ));
+                    diagnostics_info.insert(UpvarMigrationInfo::CapturingPrecise {
+                        source_expr: captured_place.info.path_expr_id,
+                        var_name: captured_place.to_string(self.tcx),
+                    });
                 }
                 ty::UpvarCapture::ByRef(..) => {}
             }
         }
 
+        debug!(?projections_list);
+        debug!(?diagnostics_info);
+
         let is_moved = !projections_list.is_empty();
+        debug!(?is_moved);
 
         let is_not_completely_captured =
             root_var_min_capture_list.iter().any(|capture| !capture.place.projections.is_empty());
+        debug!(?is_not_completely_captured);
 
         if is_moved
             && is_not_completely_captured
@@ -1066,15 +1138,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Returns a tuple containing a vector of MigrationDiagnosticInfo, as well as a String
     /// containing the reason why root variables whose HirId is contained in the vector should
     /// be captured
+    #[instrument(level = "debug", skip(self))]
     fn compute_2229_migrations(
         &self,
         closure_def_id: DefId,
         closure_span: Span,
         closure_clause: hir::CaptureBy,
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
-    ) -> (Vec<MigrationDiagnosticInfo>, String) {
+    ) -> (Vec<NeededMigration>, MigrationWarningReason) {
         let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) else {
-            return (Vec::new(), String::new());
+            return (Vec::new(), MigrationWarningReason::default());
         };
 
         let mut need_migrations = Vec::new();
@@ -1083,7 +1156,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Perform auto-trait analysis
         for (&var_hir_id, _) in upvars.iter() {
-            let mut responsible_captured_hir_ids = Vec::new();
+            let mut diagnostics_info = Vec::new();
 
             let auto_trait_diagnostic = if let Some(diagnostics_info) =
                 self.compute_2229_migrations_for_trait(min_captures, var_hir_id, closure_clause)
@@ -1115,34 +1188,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             let mut capture_diagnostic = capture_diagnostic.into_iter().collect::<Vec<_>>();
             capture_diagnostic.sort();
-            for captured_info in capture_diagnostic.iter() {
+            for captures_info in capture_diagnostic {
                 // Get the auto trait reasons of why migration is needed because of that capture, if there are any
                 let capture_trait_reasons =
-                    if let Some(reasons) = auto_trait_diagnostic.get(captured_info) {
+                    if let Some(reasons) = auto_trait_diagnostic.get(&captures_info) {
                         reasons.clone()
                     } else {
                         FxHashSet::default()
                     };
 
                 // Check if migration is needed because of drop reorder as a result of that capture
-                let capture_drop_reorder_reason = drop_reorder_diagnostic.contains(captured_info);
+                let capture_drop_reorder_reason = drop_reorder_diagnostic.contains(&captures_info);
 
                 // Combine all the reasons of why the root variable should be captured as a result of
                 // auto trait implementation issues
                 auto_trait_migration_reasons.extend(capture_trait_reasons.clone());
 
-                responsible_captured_hir_ids.push((
-                    captured_info.0,
-                    captured_info.1.clone(),
-                    self.compute_2229_migrations_reasons(
+                diagnostics_info.push(MigrationLintNote {
+                    captures_info,
+                    reason: self.compute_2229_migrations_reasons(
                         capture_trait_reasons,
                         capture_drop_reorder_reason,
                     ),
-                ));
+                });
             }
 
-            if !capture_diagnostic.is_empty() {
-                need_migrations.push((var_hir_id, responsible_captured_hir_ids));
+            if !diagnostics_info.is_empty() {
+                need_migrations.push(NeededMigration { var_hir_id, diagnostics_info });
             }
         }
         (
@@ -2087,6 +2159,7 @@ fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol {
     tcx.hir().name(var_hir_id)
 }
 
+#[instrument(level = "debug", skip(tcx))]
 fn should_do_rust_2021_incompatible_closure_captures_analysis(
     tcx: TyCtxt<'_>,
     closure_id: hir::HirId,
@@ -2102,10 +2175,12 @@ fn should_do_rust_2021_incompatible_closure_captures_analysis(
 /// - s2: Comma separated names of the variables being migrated.
 fn migration_suggestion_for_2229(
     tcx: TyCtxt<'_>,
-    need_migrations: &Vec<MigrationDiagnosticInfo>,
+    need_migrations: &Vec<NeededMigration>,
 ) -> (String, String) {
-    let need_migrations_variables =
-        need_migrations.iter().map(|(v, _)| var_name(tcx, *v)).collect::<Vec<_>>();
+    let need_migrations_variables = need_migrations
+        .iter()
+        .map(|NeededMigration { var_hir_id: v, .. }| var_name(tcx, *v))
+        .collect::<Vec<_>>();
 
     let migration_ref_concat =
         need_migrations_variables.iter().map(|v| format!("&{}", v)).collect::<Vec<_>>().join(", ");
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 30aab38b1eb..06bfc427bba 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -1,3 +1,4 @@
+use crate::check::regionck::OutlivesEnvironmentExt;
 use crate::check::{FnCtxt, Inherited};
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 
@@ -11,16 +12,21 @@ use rustc_hir::intravisit::Visitor;
 use rustc_hir::itemlikevisit::ParItemLikeVisitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::ItemKind;
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::outlives::obligations::TypeOutlives;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::infer::{self, RegionckMode, SubregionOrigin};
 use rustc_middle::hir::map as hir_map;
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
-    self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
+    self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitor,
+    WithConstness,
 };
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{sym, Ident, Symbol};
-use rustc_span::Span;
-use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_span::{Span, DUMMY_SP};
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, WellFormedLoc};
 
 use std::convert::TryInto;
@@ -253,6 +259,364 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                 .emit();
         }
     }
+
+    check_gat_where_clauses(tcx, trait_item, encl_trait_def_id);
+}
+
+/// Require that the user writes where clauses on GATs for the implicit
+/// outlives bounds involving trait parameters in trait functions and
+/// lifetimes passed as GAT substs. See `self-outlives-lint` test.
+///
+/// This trait will be our running example. We are currently WF checking the `Item` item...
+///
+/// ```rust
+/// trait LendingIterator {
+///   type Item<'me>; // <-- WF checking this trait item
+///
+///   fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
+/// }
+/// ```
+fn check_gat_where_clauses(
+    tcx: TyCtxt<'_>,
+    trait_item: &hir::TraitItem<'_>,
+    encl_trait_def_id: DefId,
+) {
+    let item = tcx.associated_item(trait_item.def_id);
+    // If the current trait item isn't a type, it isn't a GAT
+    if !matches!(item.kind, ty::AssocKind::Type) {
+        return;
+    }
+    let generics: &ty::Generics = tcx.generics_of(trait_item.def_id);
+    // If the current associated type doesn't have any (own) params, it's not a GAT
+    // FIXME(jackh726): we can also warn in the more general case
+    if generics.params.len() == 0 {
+        return;
+    }
+    let associated_items: &ty::AssocItems<'_> = tcx.associated_items(encl_trait_def_id);
+    let mut clauses: Option<FxHashSet<ty::Predicate<'_>>> = None;
+    // For every function in this trait...
+    // In our example, this would be the `next` method
+    for item in
+        associated_items.in_definition_order().filter(|item| matches!(item.kind, ty::AssocKind::Fn))
+    {
+        // The clauses we that we would require from this function
+        let mut function_clauses = FxHashSet::default();
+
+        let id = hir::HirId::make_owner(item.def_id.expect_local());
+        let param_env = tcx.param_env(item.def_id.expect_local());
+
+        let sig = tcx.fn_sig(item.def_id);
+        // Get the signature using placeholders. In our example, this would
+        // convert the late-bound 'a into a free region.
+        let sig = tcx.liberate_late_bound_regions(item.def_id, sig);
+        // Collect the arguments that are given to this GAT in the return type
+        // of  the function signature. In our example, the GAT in the return
+        // type is `<Self as LendingIterator>::Item<'a>`, so 'a and Self are arguments.
+        let (regions, types) =
+            GATSubstCollector::visit(tcx, trait_item.def_id.to_def_id(), sig.output());
+
+        // If both regions and types are empty, then this GAT isn't in the
+        // return type, and we shouldn't try to do clause analysis
+        // (particularly, doing so would end up with an empty set of clauses,
+        // since the current method would require none, and we take the
+        // intersection of requirements of all methods)
+        if types.is_empty() && regions.is_empty() {
+            continue;
+        }
+
+        // The types we can assume to be well-formed. In our example, this
+        // would be &'a mut Self, from the first argument.
+        let mut wf_tys = FxHashSet::default();
+        wf_tys.extend(sig.inputs());
+
+        // For each region argument (e.g., 'a in our example), check for a
+        // relationship to the type arguments (e.g., Self). If there is an
+        // outlives relationship (`Self: 'a`), then we want to ensure that is
+        // reflected in a where clause on the GAT itself.
+        for (region, region_idx) in &regions {
+            for (ty, ty_idx) in &types {
+                // In our example, requires that Self: 'a
+                if ty_known_to_outlive(tcx, id, param_env, &wf_tys, *ty, *region) {
+                    debug!(?ty_idx, ?region_idx);
+                    debug!("required clause: {} must outlive {}", ty, region);
+                    // Translate into the generic parameters of the GAT. In
+                    // our example, the type was Self, which will also be
+                    // Self in the GAT.
+                    let ty_param = generics.param_at(*ty_idx, tcx);
+                    let ty_param = tcx.mk_ty(ty::Param(ty::ParamTy {
+                        index: ty_param.index,
+                        name: ty_param.name,
+                    }));
+                    // Same for the region. In our example, 'a corresponds
+                    // to the 'me parameter.
+                    let region_param = generics.param_at(*region_idx, tcx);
+                    let region_param =
+                        tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
+                            def_id: region_param.def_id,
+                            index: region_param.index,
+                            name: region_param.name,
+                        }));
+                    // The predicate we expect to see. (In our example,
+                    // `Self: 'me`.)
+                    let clause = ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
+                        ty_param,
+                        region_param,
+                    ));
+                    let clause = tcx.mk_predicate(ty::Binder::dummy(clause));
+                    function_clauses.insert(clause);
+                }
+            }
+        }
+
+        // For each region argument (e.g., 'a in our example), also check for a
+        // relationship to the other region arguments. If there is an
+        // outlives relationship, then we want to ensure that is
+        // reflected in a where clause on the GAT itself.
+        for (region_a, region_a_idx) in &regions {
+            for (region_b, region_b_idx) in &regions {
+                if region_a == region_b {
+                    continue;
+                }
+
+                if region_known_to_outlive(tcx, id, param_env, &wf_tys, *region_a, *region_b) {
+                    debug!(?region_a_idx, ?region_b_idx);
+                    debug!("required clause: {} must outlive {}", region_a, region_b);
+                    // Translate into the generic parameters of the GAT.
+                    let region_a_param = generics.param_at(*region_a_idx, tcx);
+                    let region_a_param =
+                        tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
+                            def_id: region_a_param.def_id,
+                            index: region_a_param.index,
+                            name: region_a_param.name,
+                        }));
+                    // Same for the region.
+                    let region_b_param = generics.param_at(*region_b_idx, tcx);
+                    let region_b_param =
+                        tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
+                            def_id: region_b_param.def_id,
+                            index: region_b_param.index,
+                            name: region_b_param.name,
+                        }));
+                    // The predicate we expect to see.
+                    let clause = ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(
+                        region_a_param,
+                        region_b_param,
+                    ));
+                    let clause = tcx.mk_predicate(ty::Binder::dummy(clause));
+                    function_clauses.insert(clause);
+                }
+            }
+        }
+
+        // Imagine we have:
+        // ```
+        // trait Foo {
+        //   type Bar<'me>;
+        //   fn gimme(&self) -> Self::Bar<'_>;
+        //   fn gimme_default(&self) -> Self::Bar<'static>;
+        // }
+        // ```
+        // We only want to require clauses on `Bar` that we can prove from *all* functions (in this
+        // case, `'me` can be `static` from `gimme_default`)
+        match clauses.as_mut() {
+            Some(clauses) => {
+                clauses.drain_filter(|p| !function_clauses.contains(p));
+            }
+            None => {
+                clauses = Some(function_clauses);
+            }
+        }
+    }
+
+    // If there are any missing clauses, emit an error
+    let mut clauses = clauses.unwrap_or_default();
+    debug!(?clauses);
+    if !clauses.is_empty() {
+        let written_predicates: ty::GenericPredicates<'_> =
+            tcx.explicit_predicates_of(trait_item.def_id);
+        let mut clauses: Vec<_> = clauses
+            .drain_filter(|clause| {
+                written_predicates.predicates.iter().find(|p| &p.0 == clause).is_none()
+            })
+            .map(|clause| format!("{}", clause))
+            .collect();
+        // We sort so that order is predictable
+        clauses.sort();
+        if !clauses.is_empty() {
+            let mut err = tcx.sess.struct_span_err(
+                trait_item.span,
+                &format!("Missing required bounds on {}", trait_item.ident),
+            );
+
+            let suggestion = format!(
+                "{} {}",
+                if !trait_item.generics.where_clause.predicates.is_empty() {
+                    ","
+                } else {
+                    " where"
+                },
+                clauses.join(", "),
+            );
+            err.span_suggestion(
+                trait_item.generics.where_clause.tail_span_for_suggestion(),
+                "add the required where clauses",
+                suggestion,
+                Applicability::MachineApplicable,
+            );
+
+            err.emit()
+        }
+    }
+}
+
+// FIXME(jackh726): refactor some of the shared logic between the two functions below
+
+/// Given a known `param_env` and a set of well formed types, can we prove that
+/// `ty` outlives `region`.
+fn ty_known_to_outlive<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    id: hir::HirId,
+    param_env: ty::ParamEnv<'tcx>,
+    wf_tys: &FxHashSet<Ty<'tcx>>,
+    ty: Ty<'tcx>,
+    region: ty::Region<'tcx>,
+) -> bool {
+    // Unfortunately, we have to use a new `InferCtxt` each call, because
+    // region constraints get added and solved there and we need to test each
+    // call individually.
+    tcx.infer_ctxt().enter(|infcx| {
+        let mut outlives_environment = OutlivesEnvironment::new(param_env);
+        outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP);
+        outlives_environment.save_implied_bounds(id);
+        let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap();
+
+        let cause = ObligationCause::new(DUMMY_SP, id, ObligationCauseCode::MiscObligation);
+
+        let sup_type = ty;
+        let sub_region = region;
+
+        let origin = SubregionOrigin::from_obligation_cause(&cause, || {
+            infer::RelateParamBound(cause.span, sup_type, None)
+        });
+
+        let outlives = &mut TypeOutlives::new(
+            &infcx,
+            tcx,
+            &region_bound_pairs,
+            Some(infcx.tcx.lifetimes.re_root_empty),
+            param_env,
+        );
+        outlives.type_must_outlive(origin, sup_type, sub_region);
+
+        let errors = infcx.resolve_regions(
+            id.expect_owner().to_def_id(),
+            &outlives_environment,
+            RegionckMode::default(),
+        );
+
+        debug!(?errors, "errors");
+
+        // If we were able to prove that the type outlives the region without
+        // an error, it must be because of the implied or explicit bounds...
+        errors.is_empty()
+    })
+}
+
+fn region_known_to_outlive<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    id: hir::HirId,
+    param_env: ty::ParamEnv<'tcx>,
+    wf_tys: &FxHashSet<Ty<'tcx>>,
+    region_a: ty::Region<'tcx>,
+    region_b: ty::Region<'tcx>,
+) -> bool {
+    // Unfortunately, we have to use a new `InferCtxt` each call, because
+    // region constraints get added and solved there and we need to test each
+    // call individually.
+    tcx.infer_ctxt().enter(|infcx| {
+        let mut outlives_environment = OutlivesEnvironment::new(param_env);
+        outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP);
+        outlives_environment.save_implied_bounds(id);
+
+        let cause = ObligationCause::new(DUMMY_SP, id, ObligationCauseCode::MiscObligation);
+
+        let origin = SubregionOrigin::from_obligation_cause(&cause, || {
+            infer::RelateRegionParamBound(cause.span)
+        });
+
+        use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate;
+        (&infcx).push_sub_region_constraint(origin, region_a, region_b);
+
+        let errors = infcx.resolve_regions(
+            id.expect_owner().to_def_id(),
+            &outlives_environment,
+            RegionckMode::default(),
+        );
+
+        debug!(?errors, "errors");
+
+        // If we were able to prove that the type outlives the region without
+        // an error, it must be because of the implied or explicit bounds...
+        errors.is_empty()
+    })
+}
+
+/// TypeVisitor that looks for uses of GATs like
+/// `<P0 as Trait<P1..Pn>>::GAT<Pn..Pm>` and adds the arguments `P0..Pm` into
+/// the two vectors, `regions` and `types` (depending on their kind). For each
+/// parameter `Pi` also track the index `i`.
+struct GATSubstCollector<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    gat: DefId,
+    // Which region appears and which parameter index its subsituted for
+    regions: FxHashSet<(ty::Region<'tcx>, usize)>,
+    // Which params appears and which parameter index its subsituted for
+    types: FxHashSet<(Ty<'tcx>, usize)>,
+}
+
+impl<'tcx> GATSubstCollector<'tcx> {
+    fn visit<T: TypeFoldable<'tcx>>(
+        tcx: TyCtxt<'tcx>,
+        gat: DefId,
+        t: T,
+    ) -> (FxHashSet<(ty::Region<'tcx>, usize)>, FxHashSet<(Ty<'tcx>, usize)>) {
+        let mut visitor = GATSubstCollector {
+            tcx,
+            gat,
+            regions: FxHashSet::default(),
+            types: FxHashSet::default(),
+        };
+        t.visit_with(&mut visitor);
+        (visitor.regions, visitor.types)
+    }
+}
+
+impl<'tcx> TypeVisitor<'tcx> for GATSubstCollector<'tcx> {
+    type BreakTy = !;
+
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        match t.kind() {
+            ty::Projection(p) if p.item_def_id == self.gat => {
+                for (idx, subst) in p.substs.iter().enumerate() {
+                    match subst.unpack() {
+                        GenericArgKind::Lifetime(lt) => {
+                            self.regions.insert((lt, idx));
+                        }
+                        GenericArgKind::Type(t) => {
+                            self.types.insert((t, idx));
+                        }
+                        _ => {}
+                    }
+                }
+            }
+            _ => {}
+        }
+        t.super_visit_with(self)
+    }
+
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.tcx)
+    }
 }
 
 fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index 96211be8cdc..a6ea8abdf3f 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -772,7 +772,7 @@ fn infer_placeholder_type<'a>(
                 } else {
                     err.span_note(
                         tcx.hir().body(body_id).value.span,
-                        &format!("however, the inferred type `{}` cannot be named", ty.to_string()),
+                        &format!("however, the inferred type `{}` cannot be named", ty),
                     );
                 }
             }
@@ -796,7 +796,7 @@ fn infer_placeholder_type<'a>(
                 } else {
                     diag.span_note(
                         tcx.hir().body(body_id).value.span,
-                        &format!("however, the inferred type `{}` cannot be named", ty.to_string()),
+                        &format!("however, the inferred type `{}` cannot be named", ty),
                     );
                 }
             }
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index 017e7ad8ca7..f90cfb88491 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -70,6 +70,7 @@ This API is completely unstable and subject to change.
 #![feature(never_type)]
 #![feature(slice_partition_dedup)]
 #![feature(control_flow_enum)]
+#![feature(hash_drain_filter)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 34d2cfc8e2c..5dda7bfa37c 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -104,6 +104,7 @@
 #![feature(extend_one)]
 #![feature(fmt_internals)]
 #![feature(fn_traits)]
+#![feature(inherent_ascii_escape)]
 #![feature(inplace_iteration)]
 #![feature(iter_advance_by)]
 #![feature(iter_zip)]
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index c0ca068de9c..4fb2f0c8530 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -318,6 +318,8 @@ impl<T: ?Sized> !marker::Sync for Rc<T> {}
 
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Rc<T> {}
+#[stable(feature = "rc_ref_unwind_safe", since = "1.58.0")]
+impl<T: RefUnwindSafe + ?Sized> RefUnwindSafe for Rc<T> {}
 
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index 860f21085f3..ae730be0d25 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -108,6 +108,8 @@ pub use core::slice::ArrayChunks;
 pub use core::slice::ArrayChunksMut;
 #[unstable(feature = "array_windows", issue = "75027")]
 pub use core::slice::ArrayWindows;
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+pub use core::slice::EscapeAscii;
 #[stable(feature = "slice_get_slice", since = "1.28.0")]
 pub use core::slice::SliceIndex;
 #[stable(feature = "from_ref", since = "1.28.0")]
@@ -130,6 +132,8 @@ pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut};
 pub use core::slice::{RSplit, RSplitMut};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut};
+#[stable(feature = "split_inclusive", since = "1.51.0")]
+pub use core::slice::{SplitInclusive, SplitInclusiveMut};
 
 ////////////////////////////////////////////////////////////////////////////////
 // Basic slice extension methods
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 3b875477df3..104f5556566 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -46,7 +46,7 @@ pub use core::str::pattern;
 pub use core::str::EncodeUtf16;
 #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
 pub use core::str::SplitAsciiWhitespace;
-#[stable(feature = "split_inclusive", since = "1.53.0")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
 pub use core::str::SplitInclusive;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::str::SplitWhitespace;
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 18ebf1cbb10..0c00db5fdf3 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -94,7 +94,13 @@ depending on the target pointer size.
 }
 
 macro_rules! widening_impl {
-    ($SelfT:ty, $WideT:ty, $BITS:literal) => {
+    ($SelfT:ty, $WideT:ty, $BITS:literal, unsigned) => {
+        widening_impl!($SelfT, $WideT, $BITS, "");
+    };
+    ($SelfT:ty, $WideT:ty, $BITS:literal, signed) => {
+        widening_impl!($SelfT, $WideT, $BITS, "# //");
+    };
+    ($SelfT:ty, $WideT:ty, $BITS:literal, $AdaptiveTestPrefix:literal) => {
         /// Calculates the complete product `self * rhs` without the possibility to overflow.
         ///
         /// This returns the low-order (wrapping) bits and the high-order (overflow) bits
@@ -148,6 +154,33 @@ macro_rules! widening_impl {
         /// assert_eq!(5u32.carrying_mul(2, 10), (20, 0));
         /// assert_eq!(1_000_000_000u32.carrying_mul(10, 0), (1410065408, 2));
         /// assert_eq!(1_000_000_000u32.carrying_mul(10, 10), (1410065418, 2));
+        #[doc = concat!($AdaptiveTestPrefix, "assert_eq!(",
+            stringify!($SelfT), "::MAX.carrying_mul(", stringify!($SelfT), "::MAX, ", stringify!($SelfT), "::MAX), ",
+            "(0, ", stringify!($SelfT), "::MAX));"
+        )]
+        /// ```
+        ///
+        /// If `carry` is zero, this is similar to [`overflowing_mul`](Self::overflowing_mul),
+        /// except that it gives the value of the overflow instead of just whether one happened:
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        /// let r = u8::carrying_mul(7, 13, 0);
+        /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(7, 13));
+        /// let r = u8::carrying_mul(13, 42, 0);
+        /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(13, 42));
+        /// ```
+        ///
+        /// The value of the first field in the returned tuple matches what you'd get
+        /// by combining the [`wrapping_mul`](Self::wrapping_mul) and
+        /// [`wrapping_add`](Self::wrapping_add) methods:
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        /// assert_eq!(
+        ///     789_u16.carrying_mul(456, 123).0,
+        ///     789_u16.wrapping_mul(456).wrapping_add(123),
+        /// );
         /// ```
         #[unstable(feature = "bigint_helper_methods", issue = "85532")]
         #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
@@ -168,33 +201,33 @@ macro_rules! widening_impl {
 
 #[lang = "i8"]
 impl i8 {
-    widening_impl! { i8, i16, 8 }
     int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48",
     "[0x12]", "[0x12]", "", "" }
+    widening_impl! { i8, i16, 8, signed }
 }
 
 #[lang = "i16"]
 impl i16 {
-    widening_impl! { i16, i32, 16 }
     int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412",
     "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
+    widening_impl! { i16, i32, 16, signed }
 }
 
 #[lang = "i32"]
 impl i32 {
-    widening_impl! { i32, i64, 32 }
     int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
     "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
     "[0x12, 0x34, 0x56, 0x78]", "", "" }
+    widening_impl! { i32, i64, 32, signed }
 }
 
 #[lang = "i64"]
 impl i64 {
-    widening_impl! { i64, i128, 64 }
     int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12,
     "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
     "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
     "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" }
+    widening_impl! { i64, i128, 64, signed }
 }
 
 #[lang = "i128"]
@@ -212,31 +245,31 @@ impl i128 {
 #[cfg(target_pointer_width = "16")]
 #[lang = "isize"]
 impl isize {
-    widening_impl! { isize, i32, 16 }
     int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234",
     "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    widening_impl! { isize, i32, 16, signed }
 }
 
 #[cfg(target_pointer_width = "32")]
 #[lang = "isize"]
 impl isize {
-    widening_impl! { isize, i64, 32 }
     int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
     "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
     "[0x12, 0x34, 0x56, 0x78]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    widening_impl! { isize, i64, 32, signed }
 }
 
 #[cfg(target_pointer_width = "64")]
 #[lang = "isize"]
 impl isize {
-    widening_impl! { isize, i128, 64 }
     int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807,
     12, "0xaa00000000006e1", "0x6e10aa",  "0x1234567890123456", "0x5634129078563412",
-     "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
-     "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
-     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+    "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
+    usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    widening_impl! { isize, i128, 64, signed }
 }
 
 /// If 6th bit set ascii is upper case.
@@ -244,9 +277,9 @@ const ASCII_CASE_MASK: u8 = 0b0010_0000;
 
 #[lang = "u8"]
 impl u8 {
-    widening_impl! { u8, u16, 8 }
     uint_impl! { u8, u8, i8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
     "[0x12]", "", "" }
+    widening_impl! { u8, u16, 8, unsigned }
 
     /// Checks if the value is within the ASCII range.
     ///
@@ -793,26 +826,26 @@ impl u8 {
 
 #[lang = "u16"]
 impl u16 {
-    widening_impl! { u16, u32, 16 }
     uint_impl! { u16, u16, i16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
     "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
+    widening_impl! { u16, u32, 16, unsigned }
 }
 
 #[lang = "u32"]
 impl u32 {
-    widening_impl! { u32, u64, 32 }
     uint_impl! { u32, u32, i32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
     "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
+    widening_impl! { u32, u64, 32, unsigned }
 }
 
 #[lang = "u64"]
 impl u64 {
-    widening_impl! { u64, u128, 64 }
     uint_impl! { u64, u64, i64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
     "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
     "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
     "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
     "", ""}
+    widening_impl! { u64, u128, 64, unsigned }
 }
 
 #[lang = "u128"]
@@ -830,29 +863,29 @@ impl u128 {
 #[cfg(target_pointer_width = "16")]
 #[lang = "usize"]
 impl usize {
-    widening_impl! { usize, u32, 16 }
     uint_impl! { usize, u16, isize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
     "[0x34, 0x12]", "[0x12, 0x34]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    widening_impl! { usize, u32, 16, unsigned }
 }
 #[cfg(target_pointer_width = "32")]
 #[lang = "usize"]
 impl usize {
-    widening_impl! { usize, u64, 32 }
     uint_impl! { usize, u32, isize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
     "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    widening_impl! { usize, u64, 32, unsigned }
 }
 
 #[cfg(target_pointer_width = "64")]
 #[lang = "usize"]
 impl usize {
-    widening_impl! { usize, u128, 64 }
     uint_impl! { usize, u64, isize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
     "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
     "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
-     "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
+    "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    widening_impl! { usize, u128, 64, unsigned }
 }
 
 /// A classification of floating point numbers.
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 691d0891b14..a15eabf7966 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1504,6 +1504,8 @@ macro_rules! uint_impl {
         /// additional bit of overflow. This allows for chaining together multiple additions
         /// to create "big integers" which represent larger values.
         ///
+        #[doc = concat!("This can be thought of as a ", stringify!($BITS), "-bit \"full adder\", in the electronics sense.")]
+        ///
         /// # Examples
         ///
         /// Basic usage
@@ -1513,7 +1515,20 @@ macro_rules! uint_impl {
         #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")]
         #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, true), (8, false));")]
         #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), (0, true));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(0, true), (0, true));")]
         #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (1, true));")]
+        #[doc = concat!("assert_eq!(",
+            stringify!($SelfT), "::MAX.carrying_add(", stringify!($SelfT), "::MAX, true), ",
+            "(", stringify!($SelfT), "::MAX, true));"
+        )]
+        /// ```
+        ///
+        /// If `carry` is false, this method is equivalent to [`overflowing_add`](Self::overflowing_add):
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        #[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".carrying_add(2, false), 5_", stringify!($SelfT), ".overflowing_add(2));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), ", stringify!($SelfT), "::MAX.overflowing_add(1));")]
         /// ```
         #[unstable(feature = "bigint_helper_methods", issue = "85532")]
         #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 3a06cd04ab1..9d673d69687 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -1074,7 +1074,11 @@ impl Literal {
         if !n.is_finite() {
             panic!("Invalid float literal {}", n);
         }
-        Literal(bridge::client::Literal::float(&n.to_string()))
+        let mut repr = n.to_string();
+        if !repr.contains('.') {
+            repr.push_str(".0");
+        }
+        Literal(bridge::client::Literal::float(&repr))
     }
 
     /// Creates a new suffixed floating-point literal.
@@ -1115,7 +1119,11 @@ impl Literal {
         if !n.is_finite() {
             panic!("Invalid float literal {}", n);
         }
-        Literal(bridge::client::Literal::float(&n.to_string()))
+        let mut repr = n.to_string();
+        if !repr.contains('.') {
+            repr.push_str(".0");
+        }
+        Literal(bridge::client::Literal::float(&repr))
     }
 
     /// Creates a new suffixed floating-point literal.
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 6bc445c6f2b..248ecdf4bef 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -15,7 +15,7 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
-libc = { version = "0.2.103", default-features = false, features = ['rustc-dep-of-std'] }
+libc = { version = "0.2.106", default-features = false, features = ['rustc-dep-of-std'] }
 compiler_builtins = { version = "0.1.44" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs
index 30eeac14b43..01392ffab79 100644
--- a/library/std/src/os/raw/mod.rs
+++ b/library/std/src/os/raw/mod.rs
@@ -165,7 +165,14 @@ pub use core::ffi::c_void;
 #[unstable(feature = "c_size_t", issue = "88345")]
 pub type c_size_t = usize;
 
-/// Equivalent to C's `ssize_t` type, from `stddef.h` (or `cstddef` for C++).
+/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++).
+///
+/// This type is currently always [`isize`], however in the future there may be
+/// platforms where this is not the case.
+#[unstable(feature = "c_size_t", issue = "88345")]
+pub type c_ptrdiff_t = isize;
+
+/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type.
 ///
 /// This type is currently always [`isize`], however in the future there may be
 /// platforms where this is not the case.
diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs
index 4feb9c5a6d7..bb9fa54d02e 100644
--- a/library/std/src/sys/itron/thread.rs
+++ b/library/std/src/sys/itron/thread.rs
@@ -347,6 +347,6 @@ unsafe fn terminate_and_delete_current_task() -> ! {
     unsafe { crate::hint::unreachable_unchecked() };
 }
 
-pub fn available_concurrency() -> io::Result<crate::num::NonZeroUsize> {
+pub fn available_parallelism() -> io::Result<crate::num::NonZeroUsize> {
     super::unsupported()
 }
diff --git a/library/std/src/sys/windows/thread_local_dtor.rs b/library/std/src/sys/windows/thread_local_dtor.rs
index 7be13bc4b2b..25d1c6e8e87 100644
--- a/library/std/src/sys/windows/thread_local_dtor.rs
+++ b/library/std/src/sys/windows/thread_local_dtor.rs
@@ -1,4 +1,28 @@
+//! Implements thread-local destructors that are not associated with any
+//! particular data.
+
 #![unstable(feature = "thread_local_internals", issue = "none")]
 #![cfg(target_thread_local)]
 
-pub use crate::sys_common::thread_local_dtor::register_dtor_fallback as register_dtor;
+// Using a per-thread list avoids the problems in synchronizing global state.
+#[thread_local]
+static mut DESTRUCTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new();
+
+pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
+    DESTRUCTORS.push((t, dtor));
+}
+
+/// Runs destructors. This should not be called until thread exit.
+pub unsafe fn run_keyless_dtors() {
+    // Drop all the destructors.
+    //
+    // Note: While this is potentially an infinite loop, it *should* be
+    // the case that this loop always terminates because we provide the
+    // guarantee that a TLS key cannot be set after it is flagged for
+    // destruction.
+    while let Some((ptr, dtor)) = DESTRUCTORS.pop() {
+        (dtor)(ptr);
+    }
+    // We're done so free the memory.
+    DESTRUCTORS = Vec::new();
+}
diff --git a/library/std/src/sys/windows/thread_local_key.rs b/library/std/src/sys/windows/thread_local_key.rs
index 0bc51114665..ec670238e6f 100644
--- a/library/std/src/sys/windows/thread_local_key.rs
+++ b/library/std/src/sys/windows/thread_local_key.rs
@@ -196,6 +196,8 @@ pub static p_thread_callback: unsafe extern "system" fn(c::LPVOID, c::DWORD, c::
 unsafe extern "system" fn on_tls_callback(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID) {
     if dwReason == c::DLL_THREAD_DETACH || dwReason == c::DLL_PROCESS_DETACH {
         run_dtors();
+        #[cfg(target_thread_local)]
+        super::thread_local_dtor::run_keyless_dtors();
     }
 
     // See comments above for what this is doing. Note that we don't need this
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index e7944c715ed..2a155ce3117 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -1407,6 +1407,15 @@ impl<T> JoinHandle<T> {
     pub fn join(mut self) -> Result<T> {
         self.0.join()
     }
+
+    /// Checks if the the associated thread is still running its main function.
+    ///
+    /// This might return `false` for a brief moment after the thread's main
+    /// function has returned, but before the thread itself has stopped running.
+    #[unstable(feature = "thread_is_running", issue = "90470")]
+    pub fn is_running(&self) -> bool {
+        Arc::strong_count(&self.0.packet.0) > 1
+    }
 }
 
 impl<T> AsInner<imp::Thread> for JoinHandle<T> {
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index 16ad366fc12..ca0d88135a5 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -2,9 +2,13 @@ use super::Builder;
 use crate::any::Any;
 use crate::mem;
 use crate::result;
-use crate::sync::mpsc::{channel, Sender};
+use crate::sync::{
+    mpsc::{channel, Sender},
+    Arc, Barrier,
+};
 use crate::thread::{self, ThreadId};
 use crate::time::Duration;
+use crate::time::Instant;
 
 // !!! These tests are dangerous. If something is buggy, they will hang, !!!
 // !!! instead of exiting cleanly. This might wedge the buildbots.       !!!
@@ -47,6 +51,36 @@ fn test_run_basic() {
 }
 
 #[test]
+fn test_is_running() {
+    let b = Arc::new(Barrier::new(2));
+    let t = thread::spawn({
+        let b = b.clone();
+        move || {
+            b.wait();
+            1234
+        }
+    });
+
+    // Thread is definitely running here, since it's still waiting for the barrier.
+    assert_eq!(t.is_running(), true);
+
+    // Unblock the barrier.
+    b.wait();
+
+    // Now check that t.is_running() becomes false within a reasonable time.
+    let start = Instant::now();
+    while t.is_running() {
+        assert!(start.elapsed() < Duration::from_secs(2));
+        thread::sleep(Duration::from_millis(15));
+    }
+
+    // Joining the thread should not block for a significant time now.
+    let join_time = Instant::now();
+    assert_eq!(t.join().unwrap(), 1234);
+    assert!(join_time.elapsed() < Duration::from_secs(2));
+}
+
+#[test]
 fn test_join_panic() {
     match thread::spawn(move || panic!()).join() {
         result::Result::Err(_) => (),
diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs
index e2aebee916d..fa23cf26896 100644
--- a/library/test/src/formatters/junit.rs
+++ b/library/test/src/formatters/junit.rs
@@ -55,8 +55,8 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
         _stdout: &[u8],
         _state: &ConsoleTestState,
     ) -> io::Result<()> {
-        // Because the testsuit node holds some of the information as attributes, we can't write it
-        // until all of the tests has ran. Instead of writting every result as they come in, we add
+        // Because the testsuite node holds some of the information as attributes, we can't write it
+        // until all of the tests have finished. Instead of writing every result as they come in, we add
         // them to a Vec and write them all at once when run is complete.
         let duration = exec_time.map(|t| t.0).unwrap_or_default();
         self.results.push((desc.clone(), result.clone(), duration));
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index d5656f0f37e..6ba1b1b6036 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -482,6 +482,7 @@ impl<'a> Builder<'a> {
                 doc::RustByExample,
                 doc::RustcBook,
                 doc::CargoBook,
+                doc::Clippy,
                 doc::EmbeddedBook,
                 doc::EditionGuide,
             ),
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index e9cc7662e63..007ca9f7f5a 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -197,7 +197,7 @@ fn copy_self_contained_objects(
     t!(fs::create_dir_all(&libdir_self_contained));
     let mut target_deps = vec![];
 
-    // Copies the CRT objects.
+    // Copies the libc and CRT objects.
     //
     // rustc historically provides a more self-contained installation for musl targets
     // not requiring the presence of a native musl toolchain. For example, it can fall back
@@ -208,7 +208,7 @@ fn copy_self_contained_objects(
         let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
             panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
         });
-        for &obj in &["crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
+        for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
             copy_and_stamp(
                 builder,
                 &libdir_self_contained,
@@ -235,7 +235,7 @@ fn copy_self_contained_objects(
                 panic!("Target {:?} does not have a \"wasi-root\" key", target.triple)
             })
             .join("lib/wasm32-wasi");
-        for &obj in &["crt1-command.o", "crt1-reactor.o"] {
+        for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
             copy_and_stamp(
                 builder,
                 &libdir_self_contained,
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 6f2470b706a..2804e7119fb 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -755,6 +755,7 @@ tool_doc!(
     "src/tools/rustfmt",
     ["rustfmt-nightly", "rustfmt-config_proc_macro"],
 );
+tool_doc!(Clippy, "clippy", "src/tools/clippy", ["clippy_utils"]);
 
 #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct ErrorIndex {
diff --git a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile
index 63836654293..2b4b78e8135 100644
--- a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile
@@ -1,3 +1,15 @@
+# We need recent curl, OpenSSL and CA certificates, so we can download further
+# dependencies in the debian:6 image. We use an ubuntu 20.04 image download
+# those.
+FROM ubuntu:20.04
+RUN apt-get update && \
+    apt-get install -y --no-install-recommends \
+        curl \
+        ca-certificates
+WORKDIR /tmp
+COPY host-x86_64/dist-x86_64-linux/download-openssl-curl.sh /tmp/
+RUN ./download-openssl-curl.sh
+
 # We use Debian 6 (glibc 2.11, kernel 2.6.32) as a common base for other
 # distros that still need Rust support: RHEL 6 (glibc 2.12, kernel 2.6.32) and
 # SLES 11 SP4 (glibc 2.11, kernel 3.0).
@@ -14,8 +26,6 @@ RUN apt-get update && \
     apt-get install --allow-unauthenticated -y --no-install-recommends \
       automake \
       bzip2 \
-      ca-certificates \
-      curl \
       file \
       g++ \
       g++-multilib \
@@ -34,11 +44,6 @@ RUN apt-get update && \
       xz-utils \
       zlib1g-dev
 
-# Install new Let's Encrypt root CA certificate and remove the expired one.
-COPY host-x86_64/shared/ISRG_Root_X1.crt /usr/local/share/ca-certificates/ISRG_Root_X1.crt
-RUN sed -i '/mozilla\/DST_Root_CA_X3\.crt/d' /etc/ca-certificates.conf
-RUN /usr/sbin/update-ca-certificates
-
 ENV PATH=/rustroot/bin:$PATH
 ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib
 ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig
@@ -50,6 +55,7 @@ COPY host-x86_64/dist-x86_64-linux/shared.sh /tmp/
 # static.rust-lang.org. This'll be used to link into libcurl below (and used
 # later as well), so build a copy of OpenSSL with dynamic libraries into our
 # generic root.
+COPY --from=0 /tmp/openssl.tar.gz /tmp/openssl.tar.gz
 COPY host-x86_64/dist-x86_64-linux/build-openssl.sh /tmp/
 RUN ./build-openssl.sh
 
@@ -59,8 +65,13 @@ RUN ./build-openssl.sh
 #
 # Note that we also disable a bunch of optional features of curl that we don't
 # really need.
+COPY --from=0 /tmp/curl.tar.xz /tmp/curl.tar.xz
 COPY host-x86_64/dist-x86_64-linux/build-curl.sh /tmp/
-RUN ./build-curl.sh && apt-get remove -y curl
+RUN ./build-curl.sh
+
+# Use up-to-date curl CA bundle
+COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem
+ENV CURL_CA_BUNDLE /tmp/cacert.pem
 
 # binutils < 2.22 has a bug where the 32-bit executables it generates
 # immediately segfault in Rust, so we need to install our own binutils.
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
index 7b560aaaaa6..50452349931 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
@@ -1,3 +1,15 @@
+# We need recent curl, OpenSSL and CA certificates, so we can download further
+# dependencies in the debian:6 image. We use an ubuntu 20.04 image download
+# those.
+FROM ubuntu:20.04
+RUN apt-get update && \
+    apt-get install -y --no-install-recommends \
+        curl \
+        ca-certificates
+WORKDIR /tmp
+COPY host-x86_64/dist-x86_64-linux/download-openssl-curl.sh /tmp/
+RUN ./download-openssl-curl.sh
+
 # We use Debian 6 (glibc 2.11, kernel 2.6.32) as a common base for other
 # distros that still need Rust support: RHEL 6 (glibc 2.12, kernel 2.6.32) and
 # SLES 11 SP4 (glibc 2.11, kernel 3.0).
@@ -14,8 +26,6 @@ RUN apt-get update && \
     apt-get install --allow-unauthenticated -y --no-install-recommends \
       automake \
       bzip2 \
-      ca-certificates \
-      curl \
       file \
       g++ \
       g++-multilib \
@@ -34,11 +44,6 @@ RUN apt-get update && \
       xz-utils \
       zlib1g-dev
 
-# Install new Let's Encrypt root CA certificate and remove the expired one.
-COPY host-x86_64/shared/ISRG_Root_X1.crt /usr/local/share/ca-certificates/ISRG_Root_X1.crt
-RUN sed -i '/mozilla\/DST_Root_CA_X3\.crt/d' /etc/ca-certificates.conf
-RUN /usr/sbin/update-ca-certificates
-
 ENV PATH=/rustroot/bin:$PATH
 ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib
 ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig
@@ -50,6 +55,7 @@ COPY host-x86_64/dist-x86_64-linux/shared.sh /tmp/
 # static.rust-lang.org. This'll be used to link into libcurl below (and used
 # later as well), so build a copy of OpenSSL with dynamic libraries into our
 # generic root.
+COPY --from=0 /tmp/openssl.tar.gz /tmp/openssl.tar.gz
 COPY host-x86_64/dist-x86_64-linux/build-openssl.sh /tmp/
 RUN ./build-openssl.sh
 
@@ -59,8 +65,13 @@ RUN ./build-openssl.sh
 #
 # Note that we also disable a bunch of optional features of curl that we don't
 # really need.
+COPY --from=0 /tmp/curl.tar.xz /tmp/curl.tar.xz
 COPY host-x86_64/dist-x86_64-linux/build-curl.sh /tmp/
-RUN ./build-curl.sh && apt-get remove -y curl
+RUN ./build-curl.sh
+
+# Use up-to-date curl CA bundle
+COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem
+ENV CURL_CA_BUNDLE /tmp/cacert.pem
 
 # binutils < 2.22 has a bug where the 32-bit executables it generates
 # immediately segfault in Rust, so we need to install our own binutils.
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh
index 6efa7897566..88ee96eaa89 100755
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh
@@ -3,18 +3,11 @@
 set -ex
 source shared.sh
 
-VERSION=7.66.0
-
-# This needs to be downloaded directly from S3, it can't go through the CDN.
-# That's because the CDN is backed by CloudFront, which requires SNI and TLSv1
-# (without paying an absurd amount of money).
-curl https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/curl-$VERSION.tar.xz \
-  | xz --decompress \
-  | tar xf -
+tar xJf curl.tar.xz
 
 mkdir curl-build
 cd curl-build
-hide_output ../curl-$VERSION/configure \
+hide_output ../curl-*/configure \
       --prefix=/rustroot \
       --with-ssl=/rustroot \
       --disable-sspi \
@@ -35,4 +28,4 @@ hide_output make install
 
 cd ..
 rm -rf curl-build
-rm -rf curl-$VERSION
+rm -rf curl-*
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh
index 34bbe19d2fa..b48b5c4c00a 100755
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh
@@ -3,21 +3,14 @@
 set -ex
 source shared.sh
 
-VERSION=1.0.2k
+tar xzf openssl.tar.gz
 
-# This needs to be downloaded directly from S3, it can't go through the CDN.
-# That's because the CDN is backed by CloudFront, which requires SNI and TLSv1
-# (without paying an absurd amount of money).
-URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/openssl-$VERSION.tar.gz
-
-curl $URL | tar xzf -
-
-cd openssl-$VERSION
+cd openssl-*
 hide_output ./config --prefix=/rustroot shared -fPIC
 hide_output make -j$(nproc)
 hide_output make install
 cd ..
-rm -rf openssl-$VERSION
+rm -rf openssl-*
 
 # Make the system cert collection available to the new install.
 ln -nsf /etc/pki/tls/cert.pem /rustroot/ssl/
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/download-openssl-curl.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/download-openssl-curl.sh
new file mode 100755
index 00000000000..ca40a8cf7da
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/download-openssl-curl.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+set -ex
+
+OPENSSL_VERSION=1.0.2k
+CURL_VERSION=7.66.0
+
+curl -f https://ci-mirrors.rust-lang.org/rustc/openssl-$OPENSSL_VERSION.tar.gz -o openssl.tar.gz
+curl -f https://ci-mirrors.rust-lang.org/rustc/curl-$CURL_VERSION.tar.xz -o curl.tar.xz
+curl -f https://curl.se/ca/cacert.pem -o cacert.pem
diff --git a/src/ci/docker/host-x86_64/shared/ISRG_Root_X1.crt b/src/ci/docker/host-x86_64/shared/ISRG_Root_X1.crt
deleted file mode 100644
index b85c8037f6b..00000000000
--- a/src/ci/docker/host-x86_64/shared/ISRG_Root_X1.crt
+++ /dev/null
@@ -1,31 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
-TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
-cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
-WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
-ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
-MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
-h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
-0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
-A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
-T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
-B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
-B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
-KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
-OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
-jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
-qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
-rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
-HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
-hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
-ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
-3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
-NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
-ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
-TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
-jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
-oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
-4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
-mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
-emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
------END CERTIFICATE-----
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index b1dacf79d26..93b4f435d4d 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -50,7 +50,8 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
       # Look for all source files involves in the COPY command
       copied_files=/tmp/.docker-copied-files.txt
       rm -f "$copied_files"
-      for i in $(sed -n -e 's/^COPY \(.*\) .*$/\1/p' "$docker_dir/$image/Dockerfile"); do
+      for i in $(sed -n -e '/^COPY --from=/! s/^COPY \(.*\) .*$/\1/p' \
+          "$docker_dir/$image/Dockerfile"); do
         # List the file names
         find "$script_dir/$i" -type f >> $copied_files
       done
diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh
index 70c57e07fde..de6b52a5e00 100755
--- a/src/ci/docker/scripts/freebsd-toolchain.sh
+++ b/src/ci/docker/scripts/freebsd-toolchain.sh
@@ -53,7 +53,7 @@ files_to_extract=(
 for lib in c cxxrt gcc_s m thr util; do
   files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*")
 done
-for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat; do
+for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat kvm; do
   files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*")
 done
 
diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md
index 3fa91bb51f0..eb181859453 100644
--- a/src/doc/rustdoc/src/SUMMARY.md
+++ b/src/doc/rustdoc/src/SUMMARY.md
@@ -1,6 +1,7 @@
 # The Rustdoc Book
 
 - [What is rustdoc?](what-is-rustdoc.md)
+- [How to read rustdoc output](how-to-read-rustdoc.md)
 - [How to write documentation](how-to-write-documentation.md)
 - [What to include (and exclude)](what-to-include.md)
 - [Command-line arguments](command-line-arguments.md)
diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md
new file mode 100644
index 00000000000..99724d859ee
--- /dev/null
+++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md
@@ -0,0 +1,107 @@
+# How to read rustdoc output
+
+Rustdoc's HTML output includes a friendly and useful navigation interface which
+makes it easier for users to navigate and understand your code.
+This chapter covers the major features of that interface,
+and is a great starting point for documentation authors and users alike.
+
+## Structure
+
+The `rustdoc` output is divided into three sections.
+Along the left side of each page is a quick navigation bar,
+which shows contextual information about the current entry.
+The rest of the page is taken up by the search interface at the top
+and the documentation for the current item below that.
+
+## The Item Documentation
+
+The majority of the screen is taken up with the documentation text for the item
+currently being viewed.
+At the top is some at-a-glance info and controls:
+
+- the type and name of the item,
+  such as "Struct `std::time::Duration`",
+- a button to copy the item's path to the clipboard,
+  which is a clipboard item
+- a button to collapse or expand the top-level documentation for that item
+  (`[+]` or `[-]`),
+- a link to the source code (`[src]`),
+  if [configured](the-doc-attribute.html#html_no_source),
+  and present (the source may not be available if
+  the documentation was created with `cargo doc --no-deps`),
+- and the version in which the item became stable,
+  if it's a stable item in the standard library.
+
+Below this is the main documentation for the item,
+including a definition or function signature if appropriate,
+followed by a list of fields or variants for Rust types.
+Finally, the page lists associated functions and trait implementations,
+including automatic and blanket implementations that `rustdoc` knows about.
+
+### Navigation
+
+Subheadings, variants, fields, and many other things in this documentation
+are anchors and can be clicked on and deep-linked to,
+which is a great way to communicate exactly what you're talking about.
+The typograpical character "§" appears next to lines with anchors on them
+when hovered or given keyboard focus.
+
+## The Navigation Bar
+
+For example, when looking at documentation for the crate root,
+it shows all the crates documented in the documentation bundle,
+and quick links to the modules, structs, traits, functions, and macros available
+from the current crate.
+At the top, it displays a [configurable logo](the-doc-attribute.html#html_logo_url)
+alongside the current crate's name and version,
+or the current item whose documentation is being displayed.
+
+## The Theme Picker and Search Interface
+
+When viewing `rustdoc`'s output in a browser with JavaScript enabled,
+a dynamic interface appears at the top of the page.
+To the left is the theme picker, denoted with a paint-brush icon,
+and the search interface, help screen, and options appear to the right of that.
+
+### The Theme Picker
+
+Clicking on the theme picker provides a list of themes -
+by default `ayu`, `light`, and `dark` -
+which are available for viewing.
+
+### The Search Interface
+
+Typing in the search bar instantly searches the available documentation for
+the string entered with a fuzzy matching algorithm that is tolerant of minor
+typos.
+
+By default, the search results give are "In Names",
+meaning that the fuzzy match is made against the names of items.
+Matching names are shown on the left, and the first few words of their
+descriptions are given on the right.
+By clicking an item, you will navigate to its particular documentation.
+
+There are two other sets of results, shown as tabs in the search results pane.
+"In Parameters" shows matches for the string in the types of parameters to
+functions, and "In Return Types" shows matches in the return types of functions.
+Both are very useful when looking for a function whose name you can't quite
+bring to mind when you know the type you have or want.
+
+When typing in the search bar, you can prefix your search term with a type
+followed by a colon (such as `mod:`) to restrict the results to just that
+kind of item. (The available items are listed in the help popup.)
+
+### Shortcuts
+
+Pressing `S` while focused elsewhere on the page will move focus to the
+search bar, and pressing `?` shows the help screen,
+which includes all these shortcuts and more.
+Pressing `T` focuses the theme picker.
+
+When the search results are focused,
+the left and right arrows move between tabs and the up and down arrows move
+among the results.
+Pressing the enter or return key opens the highlighted result.
+
+When looking at the documentation for an item, the plus and minus keys expand
+and collapse all sections in the document.
diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md
index bd7234522e1..84fc6dcc339 100644
--- a/src/doc/unstable-book/src/library-features/asm.md
+++ b/src/doc/unstable-book/src/library-features/asm.md
@@ -257,7 +257,7 @@ unsafe {
 }
 
 println!(
-    "L1 Cache: {}",
+    "L0 Cache: {}",
     ((ebx >> 22) + 1) * (((ebx >> 12) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1)
 );
 ```
@@ -885,5 +885,7 @@ The compiler performs some additional checks on options:
     - You are responsible for switching any target-specific state (e.g. thread-local storage, stack bounds).
     - The set of memory locations that you may access is the intersection of those allowed by the `asm!` blocks you entered and exited.
 - You cannot assume that an `asm!` block will appear exactly once in the output binary. The compiler is allowed to instantiate multiple copies of the `asm!` block, for example when the function containing it is inlined in multiple places.
+- On x86, inline assembly must not end with an instruction prefix (such as `LOCK`) that would apply to instructions generated by the compiler.
+  - The compiler is currently unable to detect this due to the way inline assembly is compiled, but may catch and reject this in the future.
 
 > **Note**: As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call.
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 88fffaecb93..56ae43855de 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -789,6 +789,7 @@ impl AttributesExt for [ast::Attribute] {
     fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
         let sess = tcx.sess;
         let doc_cfg_active = tcx.features().doc_cfg;
+        let doc_auto_cfg_active = tcx.features().doc_auto_cfg;
 
         fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
             let mut iter = it.into_iter();
@@ -799,24 +800,26 @@ impl AttributesExt for [ast::Attribute] {
             Some(item)
         }
 
-        let mut cfg = if doc_cfg_active {
+        let mut cfg = if doc_cfg_active || doc_auto_cfg_active {
             let mut doc_cfg = self
                 .iter()
                 .filter(|attr| attr.has_name(sym::doc))
                 .flat_map(|attr| attr.meta_item_list().unwrap_or_else(Vec::new))
                 .filter(|attr| attr.has_name(sym::cfg))
                 .peekable();
-            if doc_cfg.peek().is_some() {
+            if doc_cfg.peek().is_some() && doc_cfg_active {
                 doc_cfg
                     .filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
                     .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
-            } else {
+            } else if doc_auto_cfg_active {
                 self.iter()
                     .filter(|attr| attr.has_name(sym::cfg))
                     .filter_map(|attr| single(attr.meta_item_list()?))
                     .filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
                     .filter(|cfg| !hidden_cfg.contains(cfg))
                     .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
+            } else {
+                Cfg::True
             }
         } else {
             Cfg::True
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index f84850c0fe1..cd0f44e5696 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -20,22 +20,28 @@ crate trait DocFolder: Sized {
             StructItem(mut i) => {
                 let num_fields = i.fields.len();
                 i.fields = i.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
-                i.fields_stripped |=
-                    num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped());
+                if !i.fields_stripped {
+                    i.fields_stripped =
+                        num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped());
+                }
                 StructItem(i)
             }
             UnionItem(mut i) => {
                 let num_fields = i.fields.len();
                 i.fields = i.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
-                i.fields_stripped |=
-                    num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped());
+                if !i.fields_stripped {
+                    i.fields_stripped =
+                        num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped());
+                }
                 UnionItem(i)
             }
             EnumItem(mut i) => {
                 let num_variants = i.variants.len();
                 i.variants = i.variants.into_iter().filter_map(|x| self.fold_item(x)).collect();
-                i.variants_stripped |=
-                    num_variants != i.variants.len() || i.variants.iter().any(|f| f.is_stripped());
+                if !i.variants_stripped {
+                    i.variants_stripped = num_variants != i.variants.len()
+                        || i.variants.iter().any(|f| f.is_stripped());
+                }
                 EnumItem(i)
             }
             TraitItem(mut i) => {
@@ -46,24 +52,42 @@ crate trait DocFolder: Sized {
                 i.items = i.items.into_iter().filter_map(|x| self.fold_item(x)).collect();
                 ImplItem(i)
             }
-            VariantItem(i) => {
-                let i2 = i.clone(); // this clone is small
-                match i {
-                    Variant::Struct(mut j) => {
-                        let num_fields = j.fields.len();
-                        j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
-                        j.fields_stripped |= num_fields != j.fields.len()
+            VariantItem(i) => match i {
+                Variant::Struct(mut j) => {
+                    let num_fields = j.fields.len();
+                    j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
+                    if !j.fields_stripped {
+                        j.fields_stripped = num_fields != j.fields.len()
                             || j.fields.iter().any(|f| f.is_stripped());
-                        VariantItem(Variant::Struct(j))
-                    }
-                    Variant::Tuple(fields) => {
-                        let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
-                        VariantItem(Variant::Tuple(fields))
                     }
-                    _ => VariantItem(i2),
+                    VariantItem(Variant::Struct(j))
                 }
-            }
-            x => x,
+                Variant::Tuple(fields) => {
+                    let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
+                    VariantItem(Variant::Tuple(fields))
+                }
+                Variant::CLike => VariantItem(Variant::CLike),
+            },
+            ExternCrateItem { src: _ }
+            | ImportItem(_)
+            | FunctionItem(_)
+            | TypedefItem(_, _)
+            | OpaqueTyItem(_)
+            | StaticItem(_)
+            | ConstantItem(_)
+            | TraitAliasItem(_)
+            | TyMethodItem(_)
+            | MethodItem(_, _)
+            | StructFieldItem(_)
+            | ForeignFunctionItem(_)
+            | ForeignStaticItem(_)
+            | ForeignTypeItem
+            | MacroItem(_)
+            | ProcMacroItem(_)
+            | PrimitiveItem(_)
+            | AssocConstItem(_, _)
+            | AssocTypeItem(_, _)
+            | KeywordItem(_) => kind,
         }
     }
 
@@ -86,14 +110,12 @@ crate trait DocFolder: Sized {
     fn fold_crate(&mut self, mut c: Crate) -> Crate {
         c.module = self.fold_item(c.module).unwrap();
 
-        {
-            let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) };
-            for (k, mut v) in external_traits {
-                v.trait_.items =
-                    v.trait_.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
-                c.external_traits.borrow_mut().insert(k, v);
-            }
+        let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) };
+        for (k, mut v) in external_traits {
+            v.trait_.items = v.trait_.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
+            c.external_traits.borrow_mut().insert(k, v);
         }
+
         c
     }
 }
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index a33bb3479ce..e177a113036 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -270,12 +270,18 @@ struct Decorations {
 
 impl Decorations {
     fn new(info: DecorationInfo) -> Self {
-        let (starts, ends) = info
+        // Extract tuples (start, end, kind) into separate sequences of (start, kind) and (end).
+        let (mut starts, mut ends): (Vec<_>, Vec<_>) = info
             .0
             .into_iter()
             .map(|(kind, ranges)| ranges.into_iter().map(move |(lo, hi)| ((lo, kind), hi)))
             .flatten()
             .unzip();
+
+        // Sort the sequences in document order.
+        starts.sort_by_key(|(lo, _)| *lo);
+        ends.sort();
+
         Decorations { starts, ends }
     }
 }
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 76e46fa0aa3..069862efde6 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -461,9 +461,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             }
         }
 
-        let (mut krate, local_sources, matches) = collect_spans_and_sources(
+        let (local_sources, matches) = collect_spans_and_sources(
             tcx,
-            krate,
+            &krate,
             &src_root,
             include_sources,
             generate_link_to_definition,
@@ -522,7 +522,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         };
 
         if emit_crate {
-            krate = sources::render(&mut cx, krate)?;
+            sources::render(&mut cx, &krate)?;
         }
 
         // Build our search index
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index f78129050d7..25fef114d95 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -76,7 +76,7 @@ use crate::html::format::{
 use crate::html::highlight;
 use crate::html::markdown::{HeadingOffset, Markdown, MarkdownHtml, MarkdownSummaryLine};
 use crate::html::sources;
-use crate::scrape_examples::CallData;
+use crate::scrape_examples::{CallData, CallLocation};
 use crate::try_none;
 
 /// A pair of name and its optional document.
@@ -2594,6 +2594,21 @@ fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
         id = id
     );
 
+    // Create a URL to a particular location in a reverse-dependency's source file
+    let link_to_loc = |call_data: &CallData, loc: &CallLocation| -> (String, String) {
+        let (line_lo, line_hi) = loc.call_expr.line_span;
+        let (anchor, title) = if line_lo == line_hi {
+            ((line_lo + 1).to_string(), format!("line {}", line_lo + 1))
+        } else {
+            (
+                format!("{}-{}", line_lo + 1, line_hi + 1),
+                format!("lines {}-{}", line_lo + 1, line_hi + 1),
+            )
+        };
+        let url = format!("{}{}#{}", cx.root_path(), call_data.url, anchor);
+        (url, title)
+    };
+
     // Generate the HTML for a single example, being the title and code block
     let write_example = |w: &mut Buffer, (path, call_data): (&PathBuf, &CallData)| -> bool {
         let contents = match fs::read_to_string(&path) {
@@ -2631,15 +2646,7 @@ fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
                 let (line_lo, line_hi) = loc.call_expr.line_span;
                 let byte_range = (byte_lo - byte_min, byte_hi - byte_min);
                 let line_range = (line_lo - line_min, line_hi - line_min);
-                let (anchor, line_title) = if line_lo == line_hi {
-                    (format!("{}", line_lo + 1), format!("line {}", line_lo + 1))
-                } else {
-                    (
-                        format!("{}-{}", line_lo + 1, line_hi + 1),
-                        format!("lines {}-{}", line_lo + 1, line_hi + 1),
-                    )
-                };
-                let line_url = format!("{}{}#{}", cx.root_path(), call_data.url, anchor);
+                let (line_url, line_title) = link_to_loc(call_data, loc);
 
                 (byte_range, (line_range, line_url, line_title))
             })
@@ -2768,11 +2775,11 @@ fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
         if it.peek().is_some() {
             write!(w, r#"<div class="example-links">Additional examples can be found in:<br><ul>"#);
             it.for_each(|(_, call_data)| {
+                let (url, _) = link_to_loc(&call_data, &call_data.locations[0]);
                 write!(
                     w,
-                    r#"<li><a href="{root}{url}">{name}</a></li>"#,
-                    root = cx.root_path(),
-                    url = call_data.url,
+                    r#"<li><a href="{url}">{name}</a></li>"#,
+                    url = url,
                     name = call_data.display_name
                 );
             });
diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index 1a8562d05ea..7803a779727 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -37,21 +37,21 @@ crate enum LinkFromSrc {
 /// only keep the `lo` and `hi`.
 crate fn collect_spans_and_sources(
     tcx: TyCtxt<'_>,
-    krate: clean::Crate,
+    krate: &clean::Crate,
     src_root: &Path,
     include_sources: bool,
     generate_link_to_definition: bool,
-) -> (clean::Crate, FxHashMap<PathBuf, String>, FxHashMap<Span, LinkFromSrc>) {
+) -> (FxHashMap<PathBuf, String>, FxHashMap<Span, LinkFromSrc>) {
     let mut visitor = SpanMapVisitor { tcx, matches: FxHashMap::default() };
 
     if include_sources {
         if generate_link_to_definition {
             tcx.hir().walk_toplevel_module(&mut visitor);
         }
-        let (krate, sources) = sources::collect_local_sources(tcx, src_root, krate);
-        (krate, sources, visitor.matches)
+        let sources = sources::collect_local_sources(tcx, src_root, &krate);
+        (sources, visitor.matches)
     } else {
-        (krate, Default::default(), Default::default())
+        (Default::default(), Default::default())
     }
 }
 
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 9422f84f997..c8e93374e63 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -1,11 +1,11 @@
 use crate::clean;
 use crate::docfs::PathError;
 use crate::error::Error;
-use crate::fold::DocFolder;
 use crate::html::format::Buffer;
 use crate::html::highlight;
 use crate::html::layout;
 use crate::html::render::{Context, BASIC_KEYWORDS};
+use crate::visit::DocVisitor;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::ty::TyCtxt;
@@ -16,23 +16,25 @@ use std::ffi::OsStr;
 use std::fs;
 use std::path::{Component, Path, PathBuf};
 
-crate fn render(cx: &mut Context<'_>, krate: clean::Crate) -> Result<clean::Crate, Error> {
+crate fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), Error> {
     info!("emitting source files");
+
     let dst = cx.dst.join("src").join(&*krate.name(cx.tcx()).as_str());
     cx.shared.ensure_dir(&dst)?;
-    let mut folder = SourceCollector { dst, cx, emitted_local_sources: FxHashSet::default() };
-    Ok(folder.fold_crate(krate))
+
+    let mut collector = SourceCollector { dst, cx, emitted_local_sources: FxHashSet::default() };
+    collector.visit_crate(krate);
+    Ok(())
 }
 
 crate fn collect_local_sources<'tcx>(
     tcx: TyCtxt<'tcx>,
     src_root: &Path,
-    krate: clean::Crate,
-) -> (clean::Crate, FxHashMap<PathBuf, String>) {
+    krate: &clean::Crate,
+) -> FxHashMap<PathBuf, String> {
     let mut lsc = LocalSourcesCollector { tcx, local_sources: FxHashMap::default(), src_root };
-
-    let krate = lsc.fold_crate(krate);
-    (krate, lsc.local_sources)
+    lsc.visit_crate(krate);
+    lsc.local_sources
 }
 
 struct LocalSourcesCollector<'a, 'tcx> {
@@ -42,7 +44,7 @@ struct LocalSourcesCollector<'a, 'tcx> {
 }
 
 fn is_real_and_local(span: clean::Span, sess: &Session) -> bool {
-    span.filename(sess).is_real() && span.cnum(sess) == LOCAL_CRATE
+    span.cnum(sess) == LOCAL_CRATE && span.filename(sess).is_real()
 }
 
 impl LocalSourcesCollector<'_, '_> {
@@ -54,12 +56,13 @@ impl LocalSourcesCollector<'_, '_> {
             return;
         }
         let filename = span.filename(sess);
-        let p = match filename {
-            FileName::Real(ref file) => match file.local_path() {
-                Some(p) => p.to_path_buf(),
-                _ => return,
-            },
-            _ => return,
+        let p = if let FileName::Real(file) = filename {
+            match file.into_local_path() {
+                Some(p) => p,
+                None => return,
+            }
+        } else {
+            return;
         };
         if self.local_sources.contains_key(&*p) {
             // We've already emitted this source
@@ -79,13 +82,11 @@ impl LocalSourcesCollector<'_, '_> {
     }
 }
 
-impl DocFolder for LocalSourcesCollector<'_, '_> {
-    fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
-        self.add_local_source(&item);
+impl DocVisitor for LocalSourcesCollector<'_, '_> {
+    fn visit_item(&mut self, item: &clean::Item) {
+        self.add_local_source(item);
 
-        // FIXME: if `include_sources` isn't set and DocFolder didn't require consuming the crate by value,
-        // we could return None here without having to walk the rest of the crate.
-        Some(self.fold_item_recur(item))
+        self.visit_item_recur(item)
     }
 }
 
@@ -98,8 +99,12 @@ struct SourceCollector<'a, 'tcx> {
     emitted_local_sources: FxHashSet<PathBuf>,
 }
 
-impl DocFolder for SourceCollector<'_, '_> {
-    fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
+impl DocVisitor for SourceCollector<'_, '_> {
+    fn visit_item(&mut self, item: &clean::Item) {
+        if !self.cx.include_sources {
+            return;
+        }
+
         let tcx = self.cx.tcx();
         let span = item.span(tcx);
         let sess = tcx.sess;
@@ -107,7 +112,7 @@ impl DocFolder for SourceCollector<'_, '_> {
         // If we're not rendering sources, there's nothing to do.
         // If we're including source files, and we haven't seen this file yet,
         // then we need to render it out to the filesystem.
-        if self.cx.include_sources && is_real_and_local(span, sess) {
+        if is_real_and_local(span, sess) {
             let filename = span.filename(sess);
             let span = span.inner();
             let pos = sess.source_map().lookup_source_file(span.lo());
@@ -132,9 +137,8 @@ impl DocFolder for SourceCollector<'_, '_> {
                 }
             };
         }
-        // FIXME: if `include_sources` isn't set and DocFolder didn't require consuming the crate by value,
-        // we could return None here without having to walk the rest of the crate.
-        Some(self.fold_item_recur(item))
+
+        self.visit_item_recur(item)
     }
 }
 
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 93cbc0debb9..89a763ef6d7 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -156,7 +156,8 @@ h1.fqn > .in-band > a:hover {
 	section hierarchies. */
 h2,
 .top-doc h3,
-.top-doc h4 {
+.top-doc h4,
+.sidebar .others h3 {
 	border-bottom: 1px solid;
 }
 h3.code-header {
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index c421c6e9dc1..4b55a0a69b6 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -566,6 +566,7 @@ function hideThemeButtonState() {
     // delayed sidebar rendering.
     window.initSidebarItems = function(items) {
         var sidebar = document.getElementsByClassName("sidebar-elems")[0];
+        var others;
         var current = window.sidebarCurrent;
 
         function addSidebarCrates(crates) {
@@ -594,7 +595,7 @@ function hideThemeButtonState() {
                 li.appendChild(link);
                 ul.appendChild(li);
             }
-            sidebar.appendChild(div);
+            others.appendChild(div);
         }
 
         function block(shortty, longty) {
@@ -635,10 +636,14 @@ function hideThemeButtonState() {
                 ul.appendChild(li);
             }
             div.appendChild(ul);
-            sidebar.appendChild(div);
+            others.appendChild(div);
         }
 
         if (sidebar) {
+            others = document.createElement("div");
+            others.className = "others";
+            sidebar.appendChild(others);
+
             var isModule = hasClass(document.body, "mod");
             if (!isModule) {
                 block("primitive", "Primitive Types");
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index cead54412bb..9fafea69145 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -108,12 +108,12 @@
          data-search-js="{{static_root_path | safe}}search{{page.resource_suffix}}.js"> {#- -#}
     </div>
     <script src="{{static_root_path | safe}}main{{page.resource_suffix}}.js"></script> {#- -#}
-    {%- if layout.scrape_examples_extension -%}
-    <script src="{{static_root_path | safe}}scrape-examples{{page.resource_suffix}}.js"></script> {#- -#}
-    {%- endif -%}
     {%- for script in page.static_extra_scripts -%}
     <script src="{{static_root_path | safe}}{{script}}.js"></script> {#- -#}
     {% endfor %}
+    {%- if layout.scrape_examples_extension -%}
+    <script src="{{page.root_path | safe}}scrape-examples{{page.resource_suffix}}.js"></script> {#- -#}
+    {%- endif -%}
     {%- for script in page.extra_scripts -%}
     <script src="{{page.root_path | safe}}{{script}}.js"></script> {#- -#}
     {% endfor %}
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index b50fbf58bae..7eeb9d1fcaa 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -121,6 +121,7 @@ mod markdown;
 mod passes;
 mod scrape_examples;
 mod theme;
+mod visit;
 mod visit_ast;
 mod visit_lib;
 
diff --git a/src/librustdoc/passes/bare_urls.rs b/src/librustdoc/passes/bare_urls.rs
index 4501914fe0c..4e146a07d15 100644
--- a/src/librustdoc/passes/bare_urls.rs
+++ b/src/librustdoc/passes/bare_urls.rs
@@ -1,8 +1,8 @@
 use super::Pass;
 use crate::clean::*;
 use crate::core::DocContext;
-use crate::fold::DocFolder;
 use crate::html::markdown::main_body_opts;
+use crate::visit::DocVisitor;
 use core::ops::Range;
 use pulldown_cmark::{Event, Parser, Tag};
 use regex::Regex;
@@ -53,16 +53,17 @@ impl<'a, 'tcx> BareUrlsLinter<'a, 'tcx> {
 }
 
 crate fn check_bare_urls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
-    BareUrlsLinter { cx }.fold_crate(krate)
+    BareUrlsLinter { cx }.visit_crate(&krate);
+    krate
 }
 
-impl<'a, 'tcx> DocFolder for BareUrlsLinter<'a, 'tcx> {
-    fn fold_item(&mut self, item: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for BareUrlsLinter<'a, 'tcx> {
+    fn visit_item(&mut self, item: &Item) {
         let hir_id = match DocContext::as_local_hir_id(self.cx.tcx, item.def_id) {
             Some(hir_id) => hir_id,
             None => {
                 // If non-local, no need to check anything.
-                return Some(self.fold_item_recur(item));
+                return;
             }
         };
         let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
@@ -106,6 +107,6 @@ impl<'a, 'tcx> DocFolder for BareUrlsLinter<'a, 'tcx> {
             }
         }
 
-        Some(self.fold_item_recur(item))
+        self.visit_item_recur(item)
     }
 }
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 5e3bd41b85c..85542ebd9ac 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -1,9 +1,9 @@
 use crate::clean;
 use crate::core::DocContext;
-use crate::fold::{self, DocFolder};
 use crate::html::markdown::{find_testable_code, ErrorCodes};
 use crate::passes::check_doc_test_visibility::{should_have_doc_example, Tests};
 use crate::passes::Pass;
+use crate::visit::DocVisitor;
 use rustc_hir as hir;
 use rustc_lint::builtin::MISSING_DOCS;
 use rustc_middle::lint::LintLevelSource;
@@ -23,7 +23,7 @@ crate const CALCULATE_DOC_COVERAGE: Pass = Pass {
 
 fn calculate_doc_coverage(krate: clean::Crate, ctx: &mut DocContext<'_>) -> clean::Crate {
     let mut calc = CoverageCalculator { items: Default::default(), ctx };
-    let krate = calc.fold_crate(krate);
+    calc.visit_crate(&krate);
 
     calc.print_results();
 
@@ -182,17 +182,18 @@ impl<'a, 'b> CoverageCalculator<'a, 'b> {
     }
 }
 
-impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
-    fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
+impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
+    fn visit_item(&mut self, i: &clean::Item) {
+        if !i.def_id.is_local() {
+            // non-local items are skipped because they can be out of the users control,
+            // especially in the case of trait impls, which rustdoc eagerly inlines
+            return;
+        }
+
         match *i.kind {
-            _ if !i.def_id.is_local() => {
-                // non-local items are skipped because they can be out of the users control,
-                // especially in the case of trait impls, which rustdoc eagerly inlines
-                return Some(i);
-            }
             clean::StrippedItem(..) => {
                 // don't count items in stripped modules
-                return Some(i);
+                return;
             }
             // docs on `use` and `extern crate` statements are not displayed, so they're not
             // worth counting
@@ -269,6 +270,6 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
             }
         }
 
-        Some(self.fold_item_recur(i))
+        self.visit_item_recur(i)
     }
 }
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index b18208d26e2..fd2ab0dc97c 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -8,9 +8,9 @@ use rustc_span::{hygiene::AstPass, ExpnData, ExpnKind, FileName, InnerSpan, DUMM
 
 use crate::clean;
 use crate::core::DocContext;
-use crate::fold::DocFolder;
 use crate::html::markdown::{self, RustCodeBlock};
 use crate::passes::Pass;
+use crate::visit::DocVisitor;
 
 crate const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass {
     name: "check-code-block-syntax",
@@ -19,7 +19,8 @@ crate const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass {
 };
 
 crate fn check_code_block_syntax(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
-    SyntaxChecker { cx }.fold_crate(krate)
+    SyntaxChecker { cx }.visit_crate(&krate);
+    krate
 }
 
 struct SyntaxChecker<'a, 'tcx> {
@@ -141,8 +142,8 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> {
-    fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
+impl<'a, 'tcx> DocVisitor for SyntaxChecker<'a, 'tcx> {
+    fn visit_item(&mut self, item: &clean::Item) {
         if let Some(dox) = &item.attrs.collapsed_doc_value() {
             let sp = item.attr_span(self.cx.tcx);
             let extra = crate::html::markdown::ExtraInfo::new_did(
@@ -155,7 +156,7 @@ impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> {
             }
         }
 
-        Some(self.fold_item_recur(item))
+        self.visit_item_recur(item)
     }
 }
 
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index 69a526d4618..7d3010cf332 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -7,8 +7,8 @@ use super::Pass;
 use crate::clean;
 use crate::clean::*;
 use crate::core::DocContext;
-use crate::fold::DocFolder;
 use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
+use crate::visit::DocVisitor;
 use crate::visit_ast::inherits_doc_hidden;
 use rustc_hir as hir;
 use rustc_middle::lint::LintLevelSource;
@@ -27,17 +27,17 @@ struct DocTestVisibilityLinter<'a, 'tcx> {
 
 crate fn check_doc_test_visibility(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
     let mut coll = DocTestVisibilityLinter { cx };
-
-    coll.fold_crate(krate)
+    coll.visit_crate(&krate);
+    krate
 }
 
-impl<'a, 'tcx> DocFolder for DocTestVisibilityLinter<'a, 'tcx> {
-    fn fold_item(&mut self, item: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for DocTestVisibilityLinter<'a, 'tcx> {
+    fn visit_item(&mut self, item: &Item) {
         let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);
 
         look_for_tests(self.cx, &dox, &item);
 
-        Some(self.fold_item_recur(item))
+        self.visit_item_recur(item)
     }
 }
 
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 9b2fe0c77e6..8541e6e1881 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -32,10 +32,10 @@ use std::ops::Range;
 
 use crate::clean::{self, utils::find_nearest_parent_module, Crate, Item, ItemLink, PrimitiveType};
 use crate::core::DocContext;
-use crate::fold::DocFolder;
 use crate::html::markdown::{markdown_links, MarkdownLink};
 use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
 use crate::passes::Pass;
+use crate::visit::DocVisitor;
 
 mod early;
 crate use early::load_intra_link_crates;
@@ -47,13 +47,14 @@ crate const COLLECT_INTRA_DOC_LINKS: Pass = Pass {
 };
 
 fn collect_intra_doc_links(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
-    LinkCollector {
+    let mut collector = LinkCollector {
         cx,
         mod_ids: Vec::new(),
         kind_side_channel: Cell::new(None),
         visited_links: FxHashMap::default(),
-    }
-    .fold_crate(krate)
+    };
+    collector.visit_crate(&krate);
+    krate
 }
 
 /// Top-level errors emitted by this pass.
@@ -816,8 +817,8 @@ fn is_derive_trait_collision<T>(ns: &PerNS<Result<(Res, T), ResolutionFailure<'_
     )
 }
 
-impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
-    fn fold_item(&mut self, item: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
+    fn visit_item(&mut self, item: &Item) {
         use rustc_middle::ty::DefIdTree;
 
         let parent_node =
@@ -911,17 +912,16 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
             }
         }
 
-        Some(if item.is_mod() {
+        if item.is_mod() {
             if !inner_docs {
                 self.mod_ids.push(item.def_id.expect_def_id());
             }
 
-            let ret = self.fold_item_recur(item);
+            self.visit_item_recur(item);
             self.mod_ids.pop();
-            ret
         } else {
-            self.fold_item_recur(item)
-        })
+            self.visit_item_recur(item)
+        }
     }
 }
 
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 7a4198198fa..77513b05ff2 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -1,7 +1,7 @@
 use super::Pass;
 use crate::clean::*;
 use crate::core::DocContext;
-use crate::fold::DocFolder;
+use crate::visit::DocVisitor;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::DefId;
@@ -14,17 +14,18 @@ crate const COLLECT_TRAIT_IMPLS: Pass = Pass {
     description: "retrieves trait impls for items in the crate",
 };
 
-crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
-    let (mut krate, synth_impls) = cx.sess().time("collect_synthetic_impls", || {
+crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate {
+    let synth_impls = cx.sess().time("collect_synthetic_impls", || {
         let mut synth = SyntheticImplCollector { cx, impls: Vec::new() };
-        (synth.fold_crate(krate), synth.impls)
+        synth.visit_crate(&krate);
+        synth.impls
     });
 
     let prims: FxHashSet<PrimitiveType> = krate.primitives.iter().map(|p| p.1).collect();
 
     let crate_items = {
         let mut coll = ItemCollector::new();
-        krate = cx.sess().time("collect_items_for_trait_impls", || coll.fold_crate(krate));
+        cx.sess().time("collect_items_for_trait_impls", || coll.visit_crate(&krate));
         coll.items
     };
 
@@ -152,14 +153,13 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
         }
     }
 
-    let items = if let ModuleItem(Module { ref mut items, .. }) = *krate.module.kind {
-        items
+    if let ModuleItem(Module { items, .. }) = &mut *krate.module.kind {
+        items.extend(synth_impls);
+        items.extend(new_items);
     } else {
         panic!("collect-trait-impls can't run");
     };
 
-    items.extend(synth_impls);
-    items.extend(new_items);
     krate
 }
 
@@ -168,8 +168,8 @@ struct SyntheticImplCollector<'a, 'tcx> {
     impls: Vec<Item>,
 }
 
-impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> {
-    fn fold_item(&mut self, i: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for SyntheticImplCollector<'a, 'tcx> {
+    fn visit_item(&mut self, i: &Item) {
         if i.is_struct() || i.is_enum() || i.is_union() {
             // FIXME(eddyb) is this `doc(hidden)` check needed?
             if !self
@@ -184,7 +184,7 @@ impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> {
             }
         }
 
-        Some(self.fold_item_recur(i))
+        self.visit_item_recur(i)
     }
 }
 
@@ -199,11 +199,11 @@ impl ItemCollector {
     }
 }
 
-impl DocFolder for ItemCollector {
-    fn fold_item(&mut self, i: Item) -> Option<Item> {
+impl DocVisitor for ItemCollector {
+    fn visit_item(&mut self, i: &Item) {
         self.items.insert(i.def_id);
 
-        Some(self.fold_item_recur(i))
+        self.visit_item_recur(i)
     }
 }
 
diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs
index a3fde92d765..56b222d8932 100644
--- a/src/librustdoc/passes/html_tags.rs
+++ b/src/librustdoc/passes/html_tags.rs
@@ -1,11 +1,13 @@
 use super::Pass;
 use crate::clean::*;
 use crate::core::DocContext;
-use crate::fold::DocFolder;
 use crate::html::markdown::main_body_opts;
-use core::ops::Range;
+use crate::visit::DocVisitor;
+
 use pulldown_cmark::{Event, Parser, Tag};
+
 use std::iter::Peekable;
+use std::ops::Range;
 use std::str::CharIndices;
 
 crate const CHECK_INVALID_HTML_TAGS: Pass = Pass {
@@ -19,13 +21,11 @@ struct InvalidHtmlTagsLinter<'a, 'tcx> {
 }
 
 crate fn check_invalid_html_tags(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
-    if !cx.tcx.sess.is_nightly_build() {
-        krate
-    } else {
+    if cx.tcx.sess.is_nightly_build() {
         let mut coll = InvalidHtmlTagsLinter { cx };
-
-        coll.fold_crate(krate)
+        coll.visit_crate(&krate);
     }
+    krate
 }
 
 const ALLOWED_UNCLOSED: &[&str] = &[
@@ -165,14 +165,14 @@ fn extract_tags(
     }
 }
 
-impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> {
-    fn fold_item(&mut self, item: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
+    fn visit_item(&mut self, item: &Item) {
         let tcx = self.cx.tcx;
         let hir_id = match DocContext::as_local_hir_id(tcx, item.def_id) {
             Some(hir_id) => hir_id,
             None => {
                 // If non-local, no need to check anything.
-                return Some(self.fold_item_recur(item));
+                return;
             }
         };
         let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
@@ -217,6 +217,6 @@ impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> {
             }
         }
 
-        Some(self.fold_item_recur(item))
+        self.visit_item_recur(item)
     }
 }
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 05e746573f4..1b5a7504552 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -10,7 +10,6 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{
     self as hir,
     intravisit::{self, Visitor},
-    HirId,
 };
 use rustc_interface::interface;
 use rustc_macros::{Decodable, Encodable};
@@ -83,15 +82,10 @@ crate struct CallLocation {
 
 impl CallLocation {
     fn new(
-        tcx: TyCtxt<'_>,
         expr_span: rustc_span::Span,
-        expr_id: HirId,
+        enclosing_item_span: rustc_span::Span,
         source_file: &SourceFile,
     ) -> Self {
-        let enclosing_item_span =
-            tcx.hir().span_with_body(tcx.hir().get_parent_item(expr_id)).source_callsite();
-        assert!(enclosing_item_span.contains(expr_span));
-
         CallLocation {
             call_expr: SyntaxRange::new(expr_span, source_file),
             enclosing_item: SyntaxRange::new(enclosing_item_span, source_file),
@@ -168,13 +162,29 @@ where
         // If this span comes from a macro expansion, then the source code may not actually show
         // a use of the given item, so it would be a poor example. Hence, we skip all uses in macros.
         if span.from_expansion() {
+            trace!("Rejecting expr from macro: {:?}", span);
+            return;
+        }
+
+        // If the enclosing item has a span coming from a proc macro, then we also don't want to include
+        // the example.
+        let enclosing_item_span = tcx.hir().span_with_body(tcx.hir().get_parent_item(ex.hir_id));
+        if enclosing_item_span.from_expansion() {
+            trace!("Rejecting expr ({:?}) from macro item: {:?}", span, enclosing_item_span);
             return;
         }
 
+        assert!(
+            enclosing_item_span.contains(span),
+            "Attempted to scrape call at [{:?}] whose enclosing item [{:?}] doesn't contain the span of the call.",
+            span,
+            enclosing_item_span
+        );
+
         // Save call site if the function resolves to a concrete definition
         if let ty::FnDef(def_id, _) = ty.kind() {
-            // Ignore functions not from the crate being documented
             if self.target_crates.iter().all(|krate| *krate != def_id.krate) {
+                trace!("Rejecting expr from crate not being documented: {:?}", span);
                 return;
             }
 
@@ -198,7 +208,8 @@ where
                 let fn_key = tcx.def_path_hash(*def_id);
                 let fn_entries = self.calls.entry(fn_key).or_default();
 
-                let location = CallLocation::new(tcx, span, ex.hir_id, &file);
+                trace!("Including expr: {:?}", span);
+                let location = CallLocation::new(span, enclosing_item_span, &file);
                 fn_entries.entry(abs_path).or_insert_with(mk_call_data).locations.push(location);
             }
         }
@@ -240,6 +251,13 @@ crate fn run(
         let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates };
         tcx.hir().visit_all_item_likes(&mut finder.as_deep_visitor());
 
+        // Sort call locations within a given file in document order
+        for fn_calls in calls.values_mut() {
+            for file_calls in fn_calls.values_mut() {
+                file_calls.locations.sort_by_key(|loc| loc.call_expr.byte_span.0);
+            }
+        }
+
         // Save output to provided path
         let mut encoder = FileEncoder::new(options.output_path).map_err(|e| e.to_string())?;
         calls.encode(&mut encoder).map_err(|e| e.to_string())?;
diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs
new file mode 100644
index 00000000000..df4d1558ebd
--- /dev/null
+++ b/src/librustdoc/visit.rs
@@ -0,0 +1,71 @@
+use crate::clean::*;
+
+crate trait DocVisitor: Sized {
+    fn visit_item(&mut self, item: &Item) {
+        self.visit_item_recur(item)
+    }
+
+    /// don't override!
+    fn visit_inner_recur(&mut self, kind: &ItemKind) {
+        match kind {
+            StrippedItem(..) => unreachable!(),
+            ModuleItem(i) => {
+                self.visit_mod(i);
+                return;
+            }
+            StructItem(i) => i.fields.iter().for_each(|x| self.visit_item(x)),
+            UnionItem(i) => i.fields.iter().for_each(|x| self.visit_item(x)),
+            EnumItem(i) => i.variants.iter().for_each(|x| self.visit_item(x)),
+            TraitItem(i) => i.items.iter().for_each(|x| self.visit_item(x)),
+            ImplItem(i) => i.items.iter().for_each(|x| self.visit_item(x)),
+            VariantItem(i) => match i {
+                Variant::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)),
+                Variant::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)),
+                Variant::CLike => {}
+            },
+            ExternCrateItem { src: _ }
+            | ImportItem(_)
+            | FunctionItem(_)
+            | TypedefItem(_, _)
+            | OpaqueTyItem(_)
+            | StaticItem(_)
+            | ConstantItem(_)
+            | TraitAliasItem(_)
+            | TyMethodItem(_)
+            | MethodItem(_, _)
+            | StructFieldItem(_)
+            | ForeignFunctionItem(_)
+            | ForeignStaticItem(_)
+            | ForeignTypeItem
+            | MacroItem(_)
+            | ProcMacroItem(_)
+            | PrimitiveItem(_)
+            | AssocConstItem(_, _)
+            | AssocTypeItem(_, _)
+            | KeywordItem(_) => {}
+        }
+    }
+
+    /// don't override!
+    fn visit_item_recur(&mut self, item: &Item) {
+        match &*item.kind {
+            StrippedItem(i) => self.visit_inner_recur(i),
+            _ => self.visit_inner_recur(&item.kind),
+        }
+    }
+
+    fn visit_mod(&mut self, m: &Module) {
+        m.items.iter().for_each(|i| self.visit_item(i))
+    }
+
+    fn visit_crate(&mut self, c: &Crate) {
+        self.visit_item(&c.module);
+
+        // FIXME: make this a simple by-ref for loop once external_traits is cleaned up
+        let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) };
+        for (k, v) in external_traits {
+            v.trait_.items.iter().for_each(|i| self.visit_item(i));
+            c.external_traits.borrow_mut().insert(k, v);
+        }
+    }
+}
diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile
new file mode 100644
index 00000000000..4934e875da6
--- /dev/null
+++ b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile
@@ -0,0 +1,18 @@
+-include ../../run-make-fulldeps/tools.mk
+
+OUTPUT_DIR := "$(TMPDIR)/rustdoc"
+DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foobar_macro --crate-type dylib --print file-names -)
+
+all:
+	$(RUSTC) src/proc.rs --crate-name foobar_macro --edition=2021 --crate-type proc-macro --emit=dep-info,link
+
+	$(RUSTC) src/lib.rs --crate-name foobar --edition=2021 --crate-type lib --emit=dep-info,link
+
+	$(RUSTDOC) examples/ex.rs --crate-name ex --crate-type bin --output $(OUTPUT_DIR) \
+		--extern foobar=$(TMPDIR)/libfoobar.rlib --extern foobar_macro=$(TMPDIR)/$(DYLIB_NAME) \
+		-Z unstable-options --scrape-examples-output-path $(TMPDIR)/ex.calls --scrape-examples-target-crate foobar
+
+	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR) \
+		-Z unstable-options --with-examples $(TMPDIR)/ex.calls
+
+	$(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs
new file mode 100644
index 00000000000..4d8c8b30e31
--- /dev/null
+++ b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs
@@ -0,0 +1,27 @@
+extern crate foobar;
+extern crate foobar_macro;
+
+use foobar::*;
+use foobar_macro::*;
+
+a_proc_macro!(); // no
+
+#[an_attr_macro]
+fn a() {
+  f(); // no
+}
+
+#[an_attr_macro(with_span)]
+fn b() {
+  f(); // yes
+}
+
+fn c() {
+  a_rules_macro!(f()); // yes
+}
+
+fn d() {
+  a_rules_macro!(()); // no
+}
+
+fn main(){}
diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs
new file mode 100644
index 00000000000..bac3970a4d3
--- /dev/null
+++ b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs
@@ -0,0 +1,12 @@
+// Scraped example should only include line numbers for items b and c in ex.rs
+// @!has foobar/fn.f.html '//*[@class="line-numbers"]' '14'
+// @has foobar/fn.f.html '//*[@class="line-numbers"]' '15'
+// @has foobar/fn.f.html '//*[@class="line-numbers"]' '21'
+// @!has foobar/fn.f.html '//*[@class="line-numbers"]' '22'
+
+pub fn f() {}
+
+#[macro_export]
+macro_rules! a_rules_macro {
+  ($e:expr) => { ($e, foobar::f()); }
+}
diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs
new file mode 100644
index 00000000000..46e518fdf6a
--- /dev/null
+++ b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs
@@ -0,0 +1,39 @@
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn a_proc_macro(_item: TokenStream) -> TokenStream {
+    "fn ex() { foobar::f(); }".parse().unwrap()
+}
+
+// inserts foobar::f() to the end of the function
+#[proc_macro_attribute]
+pub fn an_attr_macro(attr: TokenStream, item: TokenStream) -> TokenStream {
+    let new_call: TokenStream = "foobar::f();".parse().unwrap();
+
+    let mut tokens = item.into_iter();
+
+    let fn_tok = tokens.next().unwrap();
+    let ident_tok = tokens.next().unwrap();
+    let args_tok = tokens.next().unwrap();
+    let body = match tokens.next().unwrap() {
+        TokenTree::Group(g) => {
+            let new_g = Group::new(g.delimiter(), new_call);
+            let mut outer_g = Group::new(
+                g.delimiter(),
+                [TokenTree::Group(g.clone()), TokenTree::Group(new_g)].into_iter().collect(),
+            );
+
+            if attr.to_string() == "with_span" {
+                outer_g.set_span(g.span());
+            }
+
+            TokenTree::Group(outer_g)
+        }
+        _ => unreachable!(),
+    };
+
+    let tokens = vec![fn_tok, ident_tok, args_tok, body].into_iter().collect::<TokenStream>();
+
+    tokens
+}
diff --git a/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs b/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs
index d6d59820876..05c18007b0c 100644
--- a/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs
+++ b/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs
@@ -1,8 +1,10 @@
 fn main() {
-    foobar::ok();
+    foobar::ok(0);
 
     // this is a
 
+    //  ..
+
     // BIG
 
     // item
diff --git a/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs b/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs
index a1133117f86..de21d9061f8 100644
--- a/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs
+++ b/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs
@@ -1,4 +1,8 @@
 fn main() {
-    foobar::ok();
+    foobar::ok(1);
     // small item
 }
+
+fn f() {
+    foobar::ok(2);
+}
diff --git a/src/test/run-make/rustdoc-scrape-examples-ordering/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-ordering/src/lib.rs
index f1b7686d368..5afffffdf99 100644
--- a/src/test/run-make/rustdoc-scrape-examples-ordering/src/lib.rs
+++ b/src/test/run-make/rustdoc-scrape-examples-ordering/src/lib.rs
@@ -1,4 +1,7 @@
 // @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]' 'ex2'
 // @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' 'ex1'
+// @has foobar/fn.ok.html '//*[@class="highlight focus"]' '1'
+// @has foobar/fn.ok.html '//*[@class="highlight"]' '2'
+// @has foobar/fn.ok.html '//*[@class="highlight focus"]' '0'
 
-pub fn ok() {}
+pub fn ok(_x: i32) {}
diff --git a/src/test/rustdoc-gui/headings.goml b/src/test/rustdoc-gui/headings.goml
index 35d772170f6..bdf17ec4570 100644
--- a/src/test/rustdoc-gui/headings.goml
+++ b/src/test/rustdoc-gui/headings.goml
@@ -109,6 +109,9 @@ assert-css: ("h6#sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0
 assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"font-size": "15.2px"})
 assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0px"})
 
+assert-text: (".sidebar .others h3", "Modules")
+assert-css: (".sidebar .others h3", {"border-bottom-width": "1px"}, ALL)
+
 goto: file://|DOC_PATH|/test_docs/union.HeavilyDocumentedUnion.html
 
 assert-css: ("h1.fqn", {"font-size": "24px"})
diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml
index eacc9f6c15f..f9c707f81e7 100644
--- a/src/test/rustdoc-gui/sidebar.goml
+++ b/src/test/rustdoc-gui/sidebar.goml
@@ -4,17 +4,17 @@ assert-text: (".sidebar > .location", "Crate test_docs")
 assert-count: (".sidebar .location", 1)
 assert-text: (".sidebar-elems > #all-types", "See all test_docs's items")
 // We check that we have the crates list and that the "current" on is "test_docs".
-assert-text: (".sidebar-elems > .crate > ul > li > a.current", "test_docs")
+assert-text: (".sidebar-elems .crate > ul > li > a.current", "test_docs")
 // And we're also supposed to have the list of items in the current module.
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Macros")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Structs")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Enums")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Traits")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(6)", "Functions")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(7)", "Type Definitions")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(8)", "Unions")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(9)", "Keywords")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(1)", "Modules")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(2)", "Macros")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(3)", "Structs")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(4)", "Enums")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(5)", "Traits")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(6)", "Functions")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(7)", "Type Definitions")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(8)", "Unions")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(9)", "Keywords")
 assert-text: ("#structs + .item-table .item-left > a", "Foo")
 click: "#structs + .item-table .item-left > a"
 
@@ -24,13 +24,13 @@ assert-count: (".sidebar .location", 2)
 assert-false: ".sidebar-elems > .crate"
 // We now go back to the crate page to click on the "lib2" crate link.
 goto: file://|DOC_PATH|/test_docs/index.html
-click: ".sidebar-elems > .crate > ul > li:first-child > a"
+click: ".sidebar-elems .crate > ul > li:first-child > a"
 
 // PAGE: lib2/index.html
 goto: file://|DOC_PATH|/lib2/index.html
 assert-text: (".sidebar > .location", "Crate lib2")
 // We check that we have the crates list and that the "current" on is now "lib2".
-assert-text: (".sidebar-elems > .crate > ul > li > a.current", "lib2")
+assert-text: (".sidebar-elems .crate > ul > li > a.current", "lib2")
 // We now go to the "foobar" function page.
 assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
 assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
@@ -57,6 +57,6 @@ assert-false: ".sidebar-elems > .crate"
 goto: ./sub_module/sub_sub_module/index.html
 assert-text: (".sidebar > .location", "Module sub_sub_module")
 // We check that we don't have the crate list.
-assert-false: ".sidebar-elems > .crate"
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Functions")
+assert-false: ".sidebar-elems .crate"
+assert-text: (".sidebar-elems .items > ul > li:nth-child(1)", "Functions")
 assert-text: ("#functions + .item-table .item-left > a", "foo")
diff --git a/src/test/rustdoc/doc-auto-cfg.rs b/src/test/rustdoc/doc-auto-cfg.rs
new file mode 100644
index 00000000000..fcdd8354569
--- /dev/null
+++ b/src/test/rustdoc/doc-auto-cfg.rs
@@ -0,0 +1,8 @@
+#![feature(doc_auto_cfg)]
+
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-test'
+#[cfg(not(test))]
+pub fn foo() {}
diff --git a/src/test/rustdoc/doc-cfg-hide.rs b/src/test/rustdoc/doc-cfg-hide.rs
index b9d0d323137..424fa6d6a91 100644
--- a/src/test/rustdoc/doc-cfg-hide.rs
+++ b/src/test/rustdoc/doc-cfg-hide.rs
@@ -1,5 +1,5 @@
 #![crate_name = "oud"]
-#![feature(doc_cfg, doc_cfg_hide)]
+#![feature(doc_auto_cfg, doc_cfg, doc_cfg_hide)]
 
 #![doc(cfg_hide(feature = "solecism"))]
 
diff --git a/src/test/rustdoc/doc-cfg-implicit.rs b/src/test/rustdoc/doc-cfg-implicit.rs
index 36c2025785d..5d17a4ede6a 100644
--- a/src/test/rustdoc/doc-cfg-implicit.rs
+++ b/src/test/rustdoc/doc-cfg-implicit.rs
@@ -1,5 +1,5 @@
 #![crate_name = "funambulism"]
-#![feature(doc_cfg)]
+#![feature(doc_auto_cfg, doc_cfg)]
 
 // @has 'funambulism/struct.Disorbed.html'
 // @count   - '//*[@class="stab portability"]' 1
diff --git a/src/test/rustdoc/feature-gate-doc_auto_cfg.rs b/src/test/rustdoc/feature-gate-doc_auto_cfg.rs
new file mode 100644
index 00000000000..da76381e480
--- /dev/null
+++ b/src/test/rustdoc/feature-gate-doc_auto_cfg.rs
@@ -0,0 +1,8 @@
+#![feature(doc_cfg)]
+
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html
+// @count - '//*[@class="item-info"]/*[@class="stab portability"]' 0
+#[cfg(not(test))]
+pub fn foo() {}
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-90465.fixed b/src/test/ui/closures/2229_closure_analysis/issue-90465.fixed
new file mode 100644
index 00000000000..4e0b18e7233
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/issue-90465.fixed
@@ -0,0 +1,35 @@
+// run-rustfix
+
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE lint level is defined here
+
+fn main() {
+    struct Foo(u32);
+    impl Drop for Foo {
+        fn drop(&mut self) {
+            println!("dropped {}", self.0);
+        }
+    }
+
+    let f0 = Foo(0);
+    let f1 = Foo(1);
+
+    let c0 = move || {
+        let _ = &f0;
+        //~^ ERROR changes to closure capture in Rust 2021 will affect drop order
+        //~| NOTE for more information
+        let _ = f0;
+        //~^ NOTE in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect
+    };
+
+    let c1 = move || {
+        let _ = &f1;
+    };
+
+    println!("dropping 0");
+    drop(c0);
+    println!("dropping 1");
+    drop(c1);
+    println!("dropped all");
+}
+//~^ NOTE in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-90465.rs b/src/test/ui/closures/2229_closure_analysis/issue-90465.rs
new file mode 100644
index 00000000000..466e6dbabc5
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/issue-90465.rs
@@ -0,0 +1,34 @@
+// run-rustfix
+
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE lint level is defined here
+
+fn main() {
+    struct Foo(u32);
+    impl Drop for Foo {
+        fn drop(&mut self) {
+            println!("dropped {}", self.0);
+        }
+    }
+
+    let f0 = Foo(0);
+    let f1 = Foo(1);
+
+    let c0 = move || {
+        //~^ ERROR changes to closure capture in Rust 2021 will affect drop order
+        //~| NOTE for more information
+        let _ = f0;
+        //~^ NOTE in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect
+    };
+
+    let c1 = move || {
+        let _ = &f1;
+    };
+
+    println!("dropping 0");
+    drop(c0);
+    println!("dropping 1");
+    drop(c1);
+    println!("dropped all");
+}
+//~^ NOTE in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr b/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr
new file mode 100644
index 00000000000..3e921dc0f8a
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr
@@ -0,0 +1,26 @@
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/issue-90465.rs:17:14
+   |
+LL |     let c0 = move || {
+   |              ^^^^^^^
+...
+LL |         let _ = f0;
+   |                 -- in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect
+...
+LL | }
+   | - in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure
+   |
+note: the lint level is defined here
+  --> $DIR/issue-90465.rs:3:9
+   |
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `f0` to be fully captured
+   |
+LL ~     let c0 = move || {
+LL +         let _ = &f0;
+   |
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed
index b0fc5120f08..26703fbf811 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed
@@ -20,8 +20,8 @@ fn test_send_trait() {
     let mut f = 10;
     let fptr = SendPointer(&mut f as *mut i32);
     thread::spawn(move || { let _ = &fptr; unsafe {
-        //~^ ERROR: `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
+        //~^ ERROR: changes to closure capture
+        //~| NOTE: in Rust 2018, this closure implements `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0 = 20;
@@ -40,8 +40,9 @@ fn test_sync_trait() {
     let f = CustomInt(&mut f as *mut i32);
     let fptr = SyncPointer(f);
     thread::spawn(move || { let _ = &fptr; unsafe {
-        //~^ ERROR: `Sync`, `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+        //~^ ERROR: changes to closure capture
+        //~| NOTE: in Rust 2018, this closure implements `Sync`
+        //~| NOTE: in Rust 2018, this closure implements `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0.0 = 20;
@@ -65,8 +66,8 @@ fn test_clone_trait() {
     let f = U(S(Foo(0)), T(0));
     let c = || {
         let _ = &f;
-        //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+        //~| NOTE: in Rust 2018, this closure implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         let f_1 = f.1;
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs
index 2bcf9a795ed..932db51d437 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs
@@ -20,8 +20,8 @@ fn test_send_trait() {
     let mut f = 10;
     let fptr = SendPointer(&mut f as *mut i32);
     thread::spawn(move || unsafe {
-        //~^ ERROR: `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
+        //~^ ERROR: changes to closure capture
+        //~| NOTE: in Rust 2018, this closure implements `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0 = 20;
@@ -40,8 +40,9 @@ fn test_sync_trait() {
     let f = CustomInt(&mut f as *mut i32);
     let fptr = SyncPointer(f);
     thread::spawn(move || unsafe {
-        //~^ ERROR: `Sync`, `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+        //~^ ERROR: changes to closure capture
+        //~| NOTE: in Rust 2018, this closure implements `Sync`
+        //~| NOTE: in Rust 2018, this closure implements `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0.0 = 20;
@@ -64,8 +65,8 @@ impl Clone for U {
 fn test_clone_trait() {
     let f = U(S(Foo(0)), T(0));
     let c = || {
-        //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+        //~| NOTE: in Rust 2018, this closure implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         let f_1 = f.1;
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr
index 8d2d3553d40..ee4907bb755 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr
@@ -1,8 +1,8 @@
-error: changes to closure capture in Rust 2021 will affect `Send` trait implementation for closure
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
   --> $DIR/auto_traits.rs:22:19
    |
 LL |     thread::spawn(move || unsafe {
-   |                   ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
+   |                   ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0` does not implement `Send`
 ...
 LL |         *fptr.0 = 20;
    |         ------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
@@ -23,11 +23,14 @@ LL |
 LL |         *fptr.0 = 20;
  ...
 
-error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
   --> $DIR/auto_traits.rs:42:19
    |
 LL |     thread::spawn(move || unsafe {
-   |                   ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+   |                   ^^^^^^^^^^^^^^
+   |                   |
+   |                   in Rust 2018, this closure implements `Sync` as `fptr` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr` is not fully captured and `fptr.0.0` does not implement `Sync`
+   |                   in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0.0` does not implement `Send`
 ...
 LL |         *fptr.0.0 = 20;
    |         --------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0`
@@ -40,14 +43,14 @@ LL |
 LL |
 LL |
 LL |
-LL |         *fptr.0.0 = 20;
+LL |
  ...
 
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
-  --> $DIR/auto_traits.rs:66:13
+error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+  --> $DIR/auto_traits.rs:67:13
    |
 LL |     let c = || {
-   |             ^^ in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
+   |             ^^ in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f` is not fully captured and `f.1` does not implement `Clone`
 ...
 LL |         let f_1 = f.1;
    |                   --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.1`
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed
index a5652154682..7df0dd76b44 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed
@@ -19,8 +19,9 @@ where
     let f = panic::AssertUnwindSafe(f);
     let result = panic::catch_unwind(move || {
         let _ = &f;
-        //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+        //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`
+        //~| NOTE: in Rust 2018, this closure implements `RefUnwindSafe`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         f.0()
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs
index d9acde073fc..d02fac7c669 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs
@@ -18,8 +18,9 @@ where
 {
     let f = panic::AssertUnwindSafe(f);
     let result = panic::catch_unwind(move || {
-        //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+        //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`
+        //~| NOTE: in Rust 2018, this closure implements `RefUnwindSafe`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         f.0()
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr
index 10816b7bc3a..74f85b6ebaa 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr
@@ -1,8 +1,11 @@
-error: changes to closure capture in Rust 2021 will affect `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
   --> $DIR/mir_calls_to_shims.rs:20:38
    |
 LL |     let result = panic::catch_unwind(move || {
-   |                                      ^^^^^^^ in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+   |                                      ^^^^^^^
+   |                                      |
+   |                                      in Rust 2018, this closure implements `UnwindSafe` as `f` implements `UnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe` because `f` is not fully captured and `f.0` does not implement `UnwindSafe`
+   |                                      in Rust 2018, this closure implements `RefUnwindSafe` as `f` implements `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `RefUnwindSafe` because `f` is not fully captured and `f.0` does not implement `RefUnwindSafe`
 ...
 LL |         f.0()
    |         --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0`
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed
index 11218eff133..2b86b0ddade 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed
@@ -18,7 +18,6 @@ impl Foo {
     }
 }
 
-
 struct S(Foo);
 
 #[derive(Clone)]
@@ -37,8 +36,8 @@ fn test_multi_issues() {
     let f2 = U(S(Foo::from("bar")), T(0));
     let c = || {
         let _ = (&f1, &f2);
-        //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured
         let _f_1 = f1.0;
@@ -57,8 +56,8 @@ fn test_capturing_all_disjoint_fields_individually() {
     let f1 = U(S(Foo::from("foo")), T(0));
     let c = || {
         let _ = &f1;
-        //~^ ERROR: `Clone` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_1 = f1.0;
@@ -83,9 +82,9 @@ fn test_capturing_several_disjoint_fields_individually_1() {
     let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
     let c = || {
         let _ = &f1;
-        //~^ ERROR: `Clone` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_0 = f1.0;
@@ -103,8 +102,8 @@ fn test_capturing_several_disjoint_fields_individually_2() {
     let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
     let c = || {
         let _ = &f1;
-        //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_0 = f1.0;
@@ -136,9 +135,10 @@ fn test_multi_traits_issues() {
     let mut f2 = 10;
     let fptr2 = SendPointer(&mut f2 as *mut i32);
     thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe {
-        //~^ ERROR: `Sync`, `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
-        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send`
+        //~^ ERROR: changes to closure capture in Rust 2021
+        //~| NOTE: in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`
+        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr1` implements `Send`
+        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
         *fptr1.0.0 = 20;
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs
index 02f2faa2e87..3cac4abfad7 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs
@@ -18,7 +18,6 @@ impl Foo {
     }
 }
 
-
 struct S(Foo);
 
 #[derive(Clone)]
@@ -36,8 +35,8 @@ fn test_multi_issues() {
     let f1 = U(S(Foo::from("foo")), T(0));
     let f2 = U(S(Foo::from("bar")), T(0));
     let c = || {
-        //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured
         let _f_1 = f1.0;
@@ -55,8 +54,8 @@ fn test_multi_issues() {
 fn test_capturing_all_disjoint_fields_individually() {
     let f1 = U(S(Foo::from("foo")), T(0));
     let c = || {
-        //~^ ERROR: `Clone` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_1 = f1.0;
@@ -80,9 +79,9 @@ impl Clone for U1 {
 fn test_capturing_several_disjoint_fields_individually_1() {
     let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
     let c = || {
-        //~^ ERROR: `Clone` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_0 = f1.0;
@@ -99,8 +98,8 @@ fn test_capturing_several_disjoint_fields_individually_1() {
 fn test_capturing_several_disjoint_fields_individually_2() {
     let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
     let c = || {
-        //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_0 = f1.0;
@@ -132,9 +131,10 @@ fn test_multi_traits_issues() {
     let mut f2 = 10;
     let fptr2 = SendPointer(&mut f2 as *mut i32);
     thread::spawn(move || unsafe {
-        //~^ ERROR: `Sync`, `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
-        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send`
+        //~^ ERROR: changes to closure capture in Rust 2021
+        //~| NOTE: in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`
+        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr1` implements `Send`
+        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
         *fptr1.0.0 = 20;
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr
index d425db5aa99..0008f1b2c07 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr
@@ -1,8 +1,8 @@
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
-  --> $DIR/multi_diagnostics.rs:38:13
+error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+  --> $DIR/multi_diagnostics.rs:37:13
    |
 LL |     let c = || {
-   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone`
 ...
 LL |         let _f_1 = f1.0;
    |                    ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
@@ -25,11 +25,11 @@ LL ~     let c = || {
 LL +         let _ = (&f1, &f2);
    |
 
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
-  --> $DIR/multi_diagnostics.rs:57:13
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
+  --> $DIR/multi_diagnostics.rs:56:13
    |
 LL |     let c = || {
-   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone`
 ...
 LL |         let _f_1 = f1.0;
    |                    ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
@@ -41,14 +41,14 @@ LL ~     let c = || {
 LL +         let _ = &f1;
    |
 
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
-  --> $DIR/multi_diagnostics.rs:82:13
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
+  --> $DIR/multi_diagnostics.rs:81:13
    |
 LL |     let c = || {
    |             ^^
    |             |
-   |             in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
-   |             in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone`
+   |             in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone`
+   |             in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.2` does not implement `Clone`
 ...
 LL |         let _f_0 = f1.0;
    |                    ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
@@ -63,11 +63,11 @@ LL ~     let c = || {
 LL +         let _ = &f1;
    |
 
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
-  --> $DIR/multi_diagnostics.rs:101:13
+error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+  --> $DIR/multi_diagnostics.rs:100:13
    |
 LL |     let c = || {
-   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone`
 ...
 LL |         let _f_0 = f1.0;
    |                    ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
@@ -88,14 +88,15 @@ LL ~     let c = || {
 LL +         let _ = &f1;
    |
 
-error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
-  --> $DIR/multi_diagnostics.rs:134:19
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
+  --> $DIR/multi_diagnostics.rs:133:19
    |
 LL |     thread::spawn(move || unsafe {
    |                   ^^^^^^^^^^^^^^
    |                   |
-   |                   in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
-   |                   in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send`
+   |                   in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Sync`
+   |                   in Rust 2018, this closure implements `Send` as `fptr1` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Send`
+   |                   in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr2` is not fully captured and `fptr2.0` does not implement `Send`
 ...
 LL |         *fptr1.0.0 = 20;
    |         ---------- in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0`
diff --git a/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr b/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr
index d9479002b6c..36d6450c9a2 100644
--- a/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr
+++ b/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr
@@ -9,7 +9,7 @@ LL |         let c1 : () = c;
    |                  expected due to this
    |
    = note: expected unit type `()`
-                found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable)]`
+                found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#25t, extern "rust-call" fn(()), _#26t]]`
 help: use parentheses to call this closure
    |
 LL |         let c1 : () = c();
diff --git a/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr b/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr
index 880e38df2d7..91926f233d3 100644
--- a/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr
+++ b/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr
@@ -9,7 +9,7 @@ LL |         let c1 : () = c;
    |                  expected due to this
    |
    = note: expected unit type `()`
-                found closure `[f<T>::{closure#0} closure_substs=(unavailable)]`
+                found closure `[f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#25t, extern "rust-call" fn(()), _#26t]]`
 help: use parentheses to call this closure
    |
 LL |         let c1 : () = c();
diff --git a/src/test/ui/closures/print/closure-print-verbose.stderr b/src/test/ui/closures/print/closure-print-verbose.stderr
index d19b07acbf1..083717b3334 100644
--- a/src/test/ui/closures/print/closure-print-verbose.stderr
+++ b/src/test/ui/closures/print/closure-print-verbose.stderr
@@ -7,7 +7,7 @@ LL |     let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
    |              expected due to this
    |
    = note: expected fn pointer `fn(u8) -> u8`
-                 found closure `[main::{closure#0} closure_substs=(unavailable)]`
+                 found closure `[main::{closure#0} closure_substs=(unavailable) substs=[i8, extern "rust-call" fn((u8,)) -> u8, _#6t]]`
 note: closures can only be coerced to `fn` types if they do not capture any variables
   --> $DIR/closure-print-verbose.rs:10:39
    |
diff --git a/src/test/ui/consts/qualif-indirect-mutation-fail.rs b/src/test/ui/consts/qualif-indirect-mutation-fail.rs
index cedead00fec..f74a25a346f 100644
--- a/src/test/ui/consts/qualif-indirect-mutation-fail.rs
+++ b/src/test/ui/consts/qualif-indirect-mutation-fail.rs
@@ -2,6 +2,7 @@
 #![feature(const_mut_refs)]
 #![feature(const_precise_live_drops)]
 #![feature(const_swap)]
+#![feature(raw_ref_op)]
 
 // Mutable borrow of a field with drop impl.
 pub const fn f() {
@@ -42,3 +43,22 @@ pub const fn g2<T>() {
     let _ = x.is_some();
     let _y = x; //~ ERROR destructors cannot be evaluated
 }
+
+// Mutable raw reference to a Drop type.
+pub const fn address_of_mut() {
+    let mut x: Option<String> = None; //~ ERROR destructors cannot be evaluated
+    &raw mut x;
+
+    let mut y: Option<String> = None; //~ ERROR destructors cannot be evaluated
+    std::ptr::addr_of_mut!(y);
+}
+
+// Const raw reference to a Drop type. Conservatively assumed to allow mutation
+// until resolution of https://github.com/rust-lang/rust/issues/56604.
+pub const fn address_of_const() {
+    let x: Option<String> = None; //~ ERROR destructors cannot be evaluated
+    &raw const x;
+
+    let y: Option<String> = None; //~ ERROR destructors cannot be evaluated
+    std::ptr::addr_of!(y);
+}
diff --git a/src/test/ui/consts/qualif-indirect-mutation-fail.stderr b/src/test/ui/consts/qualif-indirect-mutation-fail.stderr
index aa6ed465594..713df12b7a5 100644
--- a/src/test/ui/consts/qualif-indirect-mutation-fail.stderr
+++ b/src/test/ui/consts/qualif-indirect-mutation-fail.stderr
@@ -1,33 +1,57 @@
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/qualif-indirect-mutation-fail.rs:8:9
+  --> $DIR/qualif-indirect-mutation-fail.rs:9:9
    |
 LL |     let mut a: (u32, Option<String>) = (0, None);
    |         ^^^^^ constant functions cannot evaluate destructors
 
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/qualif-indirect-mutation-fail.rs:14:9
+  --> $DIR/qualif-indirect-mutation-fail.rs:15:9
    |
 LL |     let mut x = None;
    |         ^^^^^ constants cannot evaluate destructors
 
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/qualif-indirect-mutation-fail.rs:30:9
+  --> $DIR/qualif-indirect-mutation-fail.rs:31:9
    |
 LL |     let _z = x;
    |         ^^ constants cannot evaluate destructors
 
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/qualif-indirect-mutation-fail.rs:35:9
+  --> $DIR/qualif-indirect-mutation-fail.rs:36:9
    |
 LL |     let x: Option<T> = None;
    |         ^ constant functions cannot evaluate destructors
 
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/qualif-indirect-mutation-fail.rs:43:9
+  --> $DIR/qualif-indirect-mutation-fail.rs:44:9
    |
 LL |     let _y = x;
    |         ^^ constant functions cannot evaluate destructors
 
-error: aborting due to 5 previous errors
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/qualif-indirect-mutation-fail.rs:52:9
+   |
+LL |     let mut y: Option<String> = None;
+   |         ^^^^^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/qualif-indirect-mutation-fail.rs:49:9
+   |
+LL |     let mut x: Option<String> = None;
+   |         ^^^^^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/qualif-indirect-mutation-fail.rs:62:9
+   |
+LL |     let y: Option<String> = None;
+   |         ^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/qualif-indirect-mutation-fail.rs:59:9
+   |
+LL |     let x: Option<String> = None;
+   |         ^ constant functions cannot evaluate destructors
+
+error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/qualif-indirect-mutation-pass.rs b/src/test/ui/consts/qualif-indirect-mutation-pass.rs
index 35a9b70a5f6..06af6a03b8f 100644
--- a/src/test/ui/consts/qualif-indirect-mutation-pass.rs
+++ b/src/test/ui/consts/qualif-indirect-mutation-pass.rs
@@ -3,6 +3,7 @@
 #![feature(const_mut_refs)]
 #![feature(const_precise_live_drops)]
 
+// Mutable reference allows only mutation of !Drop place.
 pub const fn f() {
     let mut x: (Option<String>, u32) = (None, 0);
     let mut a = 10;
@@ -10,7 +11,14 @@ pub const fn f() {
     x.1 = a;
 }
 
+// Mutable reference allows only mutation of !Drop place.
 pub const fn g() {
     let mut a: (u32, Option<String>) = (0, None);
     let _ = &mut a.0;
 }
+
+// Shared reference does not allow for mutation.
+pub const fn h() {
+    let x: Option<String> = None;
+    let _ = &x;
+}
diff --git a/src/test/ui/extern/extern-methods.rs b/src/test/ui/extern/extern-methods.rs
index 3909b5301ad..22792c11366 100644
--- a/src/test/ui/extern/extern-methods.rs
+++ b/src/test/ui/extern/extern-methods.rs
@@ -1,5 +1,5 @@
 // run-pass
-// only-i686
+// only-x86
 
 trait A {
     extern "fastcall" fn test1(i: i32);
diff --git a/src/test/ui/extern/extern-thiscall.rs b/src/test/ui/extern/extern-thiscall.rs
index 8ce94aa71aa..717df57ec48 100644
--- a/src/test/ui/extern/extern-thiscall.rs
+++ b/src/test/ui/extern/extern-thiscall.rs
@@ -1,5 +1,5 @@
 // run-pass
-// only-i686
+// only-x86
 
 #![feature(abi_thiscall)]
 
diff --git a/src/test/ui/extern/extern-vectorcall.rs b/src/test/ui/extern/extern-vectorcall.rs
index f625eb0890f..a283573c9fb 100644
--- a/src/test/ui/extern/extern-vectorcall.rs
+++ b/src/test/ui/extern/extern-vectorcall.rs
@@ -1,7 +1,7 @@
 // run-pass
 // revisions: x64 x32
 // [x64]only-x86_64
-// [x32]only-i686
+// [x32]only-x86
 
 #![feature(abi_vectorcall)]
 
diff --git a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs
deleted file mode 100644
index 0cfd0a0b978..00000000000
--- a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Test that we allow unsizing even if there is an unchanged param in the
-// field getting unsized.
-struct A<T, U: ?Sized + 'static>(T, B<T, U>);
-struct B<T, U: ?Sized>(T, U);
-
-fn main() {
-    let x: A<[u32; 1], [u32; 1]> = A([0; 1], B([0; 1], [0; 1]));
-    let y: &A<[u32; 1], [u32]> = &x; //~ ERROR mismatched types
-    assert_eq!(y.1.1.len(), 1);
-}
diff --git a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr
deleted file mode 100644
index f62def47726..00000000000
--- a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-relaxed_struct_unsize.rs:8:34
-   |
-LL |     let y: &A<[u32; 1], [u32]> = &x;
-   |            -------------------   ^^ expected slice `[u32]`, found array `[u32; 1]`
-   |            |
-   |            expected due to this
-   |
-   = note: expected reference `&A<[u32; 1], [u32]>`
-              found reference `&A<[u32; 1], [u32; 1]>`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/generic-associated-types/collections-project-default.rs b/src/test/ui/generic-associated-types/collections-project-default.rs
index 0944bf110c1..5b94cdee7c9 100644
--- a/src/test/ui/generic-associated-types/collections-project-default.rs
+++ b/src/test/ui/generic-associated-types/collections-project-default.rs
@@ -8,7 +8,7 @@
 // check that we don't normalize with trait defaults.
 
 trait Collection<T> {
-    type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter;
+    type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter, Self: 'iter;
     type Family: CollectionFamily;
     // Test associated type defaults with parameters
     type Sibling<U>: Collection<U> =
diff --git a/src/test/ui/generic-associated-types/collections.rs b/src/test/ui/generic-associated-types/collections.rs
index f14c6dac1b1..b0f2fb3f567 100644
--- a/src/test/ui/generic-associated-types/collections.rs
+++ b/src/test/ui/generic-associated-types/collections.rs
@@ -8,7 +8,7 @@
 // run-pass
 
 trait Collection<T> {
-    type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter;
+    type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter, Self: 'iter;
     type Family: CollectionFamily;
     // Test associated type defaults with parameters
     type Sibling<U>: Collection<U> =
diff --git a/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs b/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs
index 5d3a3a89352..d7c4dbda264 100644
--- a/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs
+++ b/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs
@@ -3,7 +3,7 @@
 #![feature(generic_associated_types)]
 
 pub trait X {
-    type Y<'a>;
+    type Y<'a> where Self: 'a;
     fn m(&self) -> Self::Y<'_>;
 }
 
diff --git a/src/test/ui/generic-associated-types/issue-70303.rs b/src/test/ui/generic-associated-types/issue-70303.rs
index d238f53bde7..568996e1a17 100644
--- a/src/test/ui/generic-associated-types/issue-70303.rs
+++ b/src/test/ui/generic-associated-types/issue-70303.rs
@@ -3,7 +3,7 @@
 #![feature(generic_associated_types)]
 
 trait Document {
-    type Cursor<'a>: DocCursor<'a>;
+    type Cursor<'a>: DocCursor<'a> where Self: 'a;
 
     fn cursor(&self) -> Self::Cursor<'_>;
 }
diff --git a/src/test/ui/generic-associated-types/issue-76535.rs b/src/test/ui/generic-associated-types/issue-76535.rs
index 1dad856d5a3..20c6924afa6 100644
--- a/src/test/ui/generic-associated-types/issue-76535.rs
+++ b/src/test/ui/generic-associated-types/issue-76535.rs
@@ -3,7 +3,7 @@
 pub trait SubTrait {}
 
 pub trait SuperTrait {
-    type SubType<'a>: SubTrait;
+    type SubType<'a>: SubTrait where Self: 'a;
 
     fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>;
 }
diff --git a/src/test/ui/generic-associated-types/issue-76535.stderr b/src/test/ui/generic-associated-types/issue-76535.stderr
index 0a7eb5dde60..64eeec1b2fc 100644
--- a/src/test/ui/generic-associated-types/issue-76535.stderr
+++ b/src/test/ui/generic-associated-types/issue-76535.stderr
@@ -7,7 +7,7 @@ LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruc
 note: associated type defined here, with 1 lifetime parameter: `'a`
   --> $DIR/issue-76535.rs:6:10
    |
-LL |     type SubType<'a>: SubTrait;
+LL |     type SubType<'a>: SubTrait where Self: 'a;
    |          ^^^^^^^ --
 help: add missing lifetime argument
    |
@@ -25,7 +25,7 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
    |
 LL | pub trait SuperTrait {
    |           ---------- this trait cannot be made into an object...
-LL |     type SubType<'a>: SubTrait;
+LL |     type SubType<'a>: SubTrait where Self: 'a;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
    = help: consider moving `SubType` to another trait
 
@@ -40,7 +40,7 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
    |
 LL | pub trait SuperTrait {
    |           ---------- this trait cannot be made into an object...
-LL |     type SubType<'a>: SubTrait;
+LL |     type SubType<'a>: SubTrait where Self: 'a;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
    = help: consider moving `SubType` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>`
diff --git a/src/test/ui/generic-associated-types/issue-79422.rs b/src/test/ui/generic-associated-types/issue-79422.rs
index 7f0ac348358..47ef38ff45d 100644
--- a/src/test/ui/generic-associated-types/issue-79422.rs
+++ b/src/test/ui/generic-associated-types/issue-79422.rs
@@ -17,12 +17,12 @@ impl<'a, T> RefCont<'a, T> for Box<T> {
 }
 
 trait MapLike<K, V> {
-    type VRefCont<'a>: RefCont<'a, V>;
+    type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
     fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>;
 }
 
 impl<K: Ord, V: 'static> MapLike<K, V> for std::collections::BTreeMap<K, V> {
-    type VRefCont<'a> = &'a V;
+    type VRefCont<'a> where Self: 'a = &'a V;
     fn get<'a>(&'a self, key: &K) -> Option<&'a V> {
         std::collections::BTreeMap::get(self, key)
     }
diff --git a/src/test/ui/generic-associated-types/issue-79422.stderr b/src/test/ui/generic-associated-types/issue-79422.stderr
index b6f856a97e7..8b6f9b866e5 100644
--- a/src/test/ui/generic-associated-types/issue-79422.stderr
+++ b/src/test/ui/generic-associated-types/issue-79422.stderr
@@ -7,7 +7,7 @@ LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
 note: associated type defined here, with 1 lifetime parameter: `'a`
   --> $DIR/issue-79422.rs:20:10
    |
-LL |     type VRefCont<'a>: RefCont<'a, V>;
+LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    |          ^^^^^^^^ --
 help: add missing lifetime argument
    |
@@ -25,7 +25,7 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
    |
 LL | trait MapLike<K, V> {
    |       ------- this trait cannot be made into an object...
-LL |     type VRefCont<'a>: RefCont<'a, V>;
+LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
    = help: consider moving `VRefCont` to another trait
 
@@ -40,7 +40,7 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
    |
 LL | trait MapLike<K, V> {
    |       ------- this trait cannot be made into an object...
-LL |     type VRefCont<'a>: RefCont<'a, V>;
+LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
    = help: consider moving `VRefCont` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>`
diff --git a/src/test/ui/generic-associated-types/issue-86787.rs b/src/test/ui/generic-associated-types/issue-86787.rs
index f1f05ea6627..0f62f83e256 100644
--- a/src/test/ui/generic-associated-types/issue-86787.rs
+++ b/src/test/ui/generic-associated-types/issue-86787.rs
@@ -9,6 +9,7 @@ enum Either<L, R> {
 pub trait HasChildrenOf {
     type T;
     type TRef<'a>;
+    //~^ Missing required bounds
 
     fn ref_children<'a>(&'a self) -> Vec<Self::TRef<'a>>;
     fn take_children(self) -> Vec<Self::T>;
@@ -20,9 +21,9 @@ where
     Right: HasChildrenOf,
 {
     type T = Either<Left::T, Right::T>;
+    // We used to error below because the where clause doesn't match the trait.
+    // Now, we error early on the trait itself.
     type TRef<'a>
-    //~^ `impl` associated type signature
-    //~^^ `impl` associated type signature
     where
     <Left as HasChildrenOf>::T: 'a,
     <Right as HasChildrenOf>::T: 'a
diff --git a/src/test/ui/generic-associated-types/issue-86787.stderr b/src/test/ui/generic-associated-types/issue-86787.stderr
index 648eff77d73..87dcd875de7 100644
--- a/src/test/ui/generic-associated-types/issue-86787.stderr
+++ b/src/test/ui/generic-associated-types/issue-86787.stderr
@@ -1,32 +1,10 @@
-error: `impl` associated type signature for `TRef` doesn't match `trait` associated type signature
-  --> $DIR/issue-86787.rs:23:5
+error: Missing required bounds on TRef
+  --> $DIR/issue-86787.rs:11:5
    |
-LL |       type TRef<'a>;
-   |       -------------- expected
-...
-LL | /     type TRef<'a>
-LL | |
-LL | |
-LL | |     where
-LL | |     <Left as HasChildrenOf>::T: 'a,
-LL | |     <Right as HasChildrenOf>::T: 'a
-LL | |     = Either<&'a Left::T, &'a Right::T>;
-   | |________________________________________^ found
+LL |     type TRef<'a>;
+   |     ^^^^^^^^^^^^^-
+   |                  |
+   |                  help: add the required where clauses: `where Self: 'a`
 
-error: `impl` associated type signature for `TRef` doesn't match `trait` associated type signature
-  --> $DIR/issue-86787.rs:23:5
-   |
-LL |       type TRef<'a>;
-   |       -------------- expected
-...
-LL | /     type TRef<'a>
-LL | |
-LL | |
-LL | |     where
-LL | |     <Left as HasChildrenOf>::T: 'a,
-LL | |     <Right as HasChildrenOf>::T: 'a
-LL | |     = Either<&'a Left::T, &'a Right::T>;
-   | |________________________________________^ found
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/issue-88287.rs b/src/test/ui/generic-associated-types/issue-88287.rs
index 2e65af594a6..df5586ed422 100644
--- a/src/test/ui/generic-associated-types/issue-88287.rs
+++ b/src/test/ui/generic-associated-types/issue-88287.rs
@@ -13,7 +13,8 @@ trait SearchableResource<Criteria> {
 trait SearchableResourceExt<Criteria>: SearchableResource<Criteria> {
     type Future<'f, A: 'f + ?Sized, B: 'f>: Future<Output = Result<Vec<A::SearchResult>, ()>> + 'f
     where
-        A: SearchableResource<B>;
+        A: SearchableResource<B>,
+        Self: 'f;
 
     fn search<'c>(&'c self, client: &'c ()) -> Self::Future<'c, Self, Criteria>;
 }
@@ -29,6 +30,7 @@ where
     type Future<'f, A, B: 'f>
     where
         A: SearchableResource<B> + ?Sized + 'f,
+        Self: 'f,
     = SearchFutureTy<'f, A, B>;
 
     fn search<'c>(&'c self, _client: &'c ()) -> Self::Future<'c, Self, Criteria> {
diff --git a/src/test/ui/generic-associated-types/issue-88360.rs b/src/test/ui/generic-associated-types/issue-88360.rs
index 06af3f5ec96..8ee98201aba 100644
--- a/src/test/ui/generic-associated-types/issue-88360.rs
+++ b/src/test/ui/generic-associated-types/issue-88360.rs
@@ -1,13 +1,14 @@
 #![feature(generic_associated_types)]
 
 trait GatTrait {
-    type Gat<'a>;
+    type Gat<'a> where Self: 'a;
 
     fn test(&self) -> Self::Gat<'_>;
 }
 
 trait SuperTrait<T>
 where
+    Self: 'static,
     for<'a> Self: GatTrait<Gat<'a> = &'a T>,
 {
     fn copy(&self) -> Self::Gat<'_> where T: Copy {
diff --git a/src/test/ui/generic-associated-types/issue-88360.stderr b/src/test/ui/generic-associated-types/issue-88360.stderr
index cfbf3aaa4e6..5f769d799fa 100644
--- a/src/test/ui/generic-associated-types/issue-88360.stderr
+++ b/src/test/ui/generic-associated-types/issue-88360.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-88360.rs:14:9
+  --> $DIR/issue-88360.rs:15:9
    |
 LL | trait SuperTrait<T>
    |                  - this type parameter
diff --git a/src/test/ui/generic-associated-types/issue-88459.rs b/src/test/ui/generic-associated-types/issue-88459.rs
new file mode 100644
index 00000000000..3b26a180152
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-88459.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+
+trait Trait {
+    type Assoc<'a>;
+}
+
+fn f<T: Trait>(_: T, _: impl Fn(T::Assoc<'_>)) {}
+
+struct Type;
+
+impl Trait for Type {
+    type Assoc<'a> = ();
+}
+
+fn main() {
+    f(Type, |_|());
+}
diff --git a/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs
index b976ee3261f..bcbcfc18996 100644
--- a/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs
+++ b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs
@@ -1,7 +1,7 @@
 #![feature(generic_associated_types)]
 
 pub trait X {
-    type Y<'a>;
+    type Y<'a> where Self: 'a;
     fn m(&self) -> Self::Y<'_>;
 }
 
diff --git a/src/test/ui/generic-associated-types/self-outlives-lint.rs b/src/test/ui/generic-associated-types/self-outlives-lint.rs
new file mode 100644
index 00000000000..af90d158855
--- /dev/null
+++ b/src/test/ui/generic-associated-types/self-outlives-lint.rs
@@ -0,0 +1,173 @@
+#![feature(generic_associated_types)]
+
+// check-fail
+
+use std::fmt::Debug;
+
+// We have a `&'a self`, so we need a `Self: 'a`
+trait Iterable {
+    type Item<'x>;
+    //~^ Missing required bounds
+    fn iter<'a>(&'a self) -> Self::Item<'a>;
+}
+
+/*
+impl<T> Iterable for T {
+    type Item<'a> = &'a T;
+    fn iter<'a>(&'a self) -> Self::Item<'a> {
+        self
+    }
+}
+*/
+
+// We have a `&'a T`, so we need a `T: 'x`
+trait Deserializer<T> {
+    type Out<'x>;
+    //~^ Missing required bounds
+    fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a>;
+}
+
+/*
+impl<T> Deserializer<T> for () {
+    type Out<'a> = &'a T;
+    fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a> { input }
+}
+*/
+
+// We have a `&'b T` and a `'b: 'a`, so it is implied that `T: 'a`. Therefore, we need a `T: 'x`
+trait Deserializer2<T> {
+    type Out<'x>;
+    //~^ Missing required bounds
+    fn deserialize2<'a, 'b: 'a>(&self, input1: &'b T) -> Self::Out<'a>;
+}
+
+// We have a `&'a T` and a `&'b U`, so we need a `T: 'x` and a `U: 'y`
+trait Deserializer3<T, U> {
+    type Out<'x, 'y>;
+    //~^ Missing required bounds
+    fn deserialize2<'a, 'b>(&self, input: &'a T, input2: &'b U) -> Self::Out<'a, 'b>;
+}
+
+// `T` is a param on the function, so it can't be named by the associated type
+trait Deserializer4 {
+    type Out<'x>;
+    fn deserialize<'a, T>(&self, input: &'a T) -> Self::Out<'a>;
+}
+
+struct Wrap<T>(T);
+
+// We pass `Wrap<T>` and we see `&'z Wrap<T>`, so we require `D: 'x`
+trait Des {
+    type Out<'x, D>;
+    //~^ Missing required bounds
+    fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, Wrap<T>>;
+}
+/*
+impl Des for () {
+    type Out<'x, D> = &'x D; // Not okay
+    fn des<'a, T>(&self, data: &'a Wrap<T>) -> Self::Out<'a, Wrap<T>> {
+        data
+    }
+}
+*/
+
+// We have `T` and `'z` as GAT substs. Because of `&'z Wrap<T>`, there is an
+// implied bound that `T: 'z`, so we require `D: 'x`
+trait Des2 {
+    type Out<'x, D>;
+    //~^ Missing required bounds
+    fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, T>;
+}
+/*
+impl Des2 for () {
+    type Out<'x, D> = &'x D;
+    fn des<'a, T>(&self, data: &'a Wrap<T>) -> Self::Out<'a, T> {
+        &data.0
+    }
+}
+*/
+
+// We see `&'z T`, so we require `D: 'x`
+trait Des3 {
+    type Out<'x, D>;
+    //~^ Missing required bounds
+    fn des<'z, T>(&self, data: &'z T) -> Self::Out<'z, T>;
+}
+/*
+impl Des3 for () {
+    type Out<'x, D> = &'x D;
+    fn des<'a, T>(&self, data: &'a T) -> Self::Out<'a, T> {
+          data
+    }
+}
+*/
+
+// Similar case to before, except with GAT.
+trait NoGat<'a> {
+    type Bar;
+    fn method(&'a self) -> Self::Bar;
+}
+
+// Lifetime is not on function; except `Self: 'a`
+// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one
+trait TraitLifetime<'a> {
+    type Bar<'b>;
+    //~^ Missing required bounds
+    fn method(&'a self) -> Self::Bar<'a>;
+}
+
+// Like above, but we have a where clause that can prove what we want
+// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one
+trait TraitLifetimeWhere<'a> where Self: 'a {
+    type Bar<'b>;
+    //~^ Missing required bounds
+    fn method(&'a self) -> Self::Bar<'a>;
+}
+
+// Explicit bound instead of implicit; we want to still error
+trait ExplicitBound {
+    type Bar<'b>;
+    //~^ Missing required bounds
+    fn method<'b>(&self, token: &'b ()) -> Self::Bar<'b> where Self: 'b;
+}
+
+// The use of the GAT here is not in the return, we don't want to error
+trait NotInReturn {
+    type Bar<'b>;
+    fn method<'b>(&'b self) where Self::Bar<'b>: Debug;
+}
+
+// We obviously error for `Iterator`, but we should also error for `Item`
+trait IterableTwo {
+    type Item<'a>;
+    type Iterator<'a>: Iterator<Item = Self::Item<'a>>;
+    //~^ Missing required bounds
+    fn iter<'a>(&'a self) -> Self::Iterator<'a>;
+}
+
+// We also should report region outlives clauses
+trait RegionOutlives {
+    type Bar<'a, 'b>;
+    //~^ Missing required bounds
+    fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y>;
+}
+
+/*
+impl Foo for () {
+    type Bar<'a, 'b> = &'a &'b ();
+    fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y> {
+        input
+    }
+}
+*/
+
+// If there are multiple methods that return the GAT, require a set of clauses
+// that can be satisfied by *all* methods
+trait MultipleMethods {
+    type Bar<'me>;
+
+    fn gimme<'a>(&'a self) -> Self::Bar<'a>;
+    fn gimme_default(&self) -> Self::Bar<'static>;
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/self-outlives-lint.stderr b/src/test/ui/generic-associated-types/self-outlives-lint.stderr
new file mode 100644
index 00000000000..bf85780f69f
--- /dev/null
+++ b/src/test/ui/generic-associated-types/self-outlives-lint.stderr
@@ -0,0 +1,98 @@
+error: Missing required bounds on Item
+  --> $DIR/self-outlives-lint.rs:9:5
+   |
+LL |     type Item<'x>;
+   |     ^^^^^^^^^^^^^-
+   |                  |
+   |                  help: add the required where clauses: `where Self: 'x`
+
+error: Missing required bounds on Out
+  --> $DIR/self-outlives-lint.rs:25:5
+   |
+LL |     type Out<'x>;
+   |     ^^^^^^^^^^^^-
+   |                 |
+   |                 help: add the required where clauses: `where T: 'x`
+
+error: Missing required bounds on Out
+  --> $DIR/self-outlives-lint.rs:39:5
+   |
+LL |     type Out<'x>;
+   |     ^^^^^^^^^^^^-
+   |                 |
+   |                 help: add the required where clauses: `where T: 'x`
+
+error: Missing required bounds on Out
+  --> $DIR/self-outlives-lint.rs:46:5
+   |
+LL |     type Out<'x, 'y>;
+   |     ^^^^^^^^^^^^^^^^-
+   |                     |
+   |                     help: add the required where clauses: `where T: 'x, U: 'y`
+
+error: Missing required bounds on Out
+  --> $DIR/self-outlives-lint.rs:61:5
+   |
+LL |     type Out<'x, D>;
+   |     ^^^^^^^^^^^^^^^-
+   |                    |
+   |                    help: add the required where clauses: `where D: 'x`
+
+error: Missing required bounds on Out
+  --> $DIR/self-outlives-lint.rs:77:5
+   |
+LL |     type Out<'x, D>;
+   |     ^^^^^^^^^^^^^^^-
+   |                    |
+   |                    help: add the required where clauses: `where D: 'x`
+
+error: Missing required bounds on Out
+  --> $DIR/self-outlives-lint.rs:92:5
+   |
+LL |     type Out<'x, D>;
+   |     ^^^^^^^^^^^^^^^-
+   |                    |
+   |                    help: add the required where clauses: `where D: 'x`
+
+error: Missing required bounds on Bar
+  --> $DIR/self-outlives-lint.rs:114:5
+   |
+LL |     type Bar<'b>;
+   |     ^^^^^^^^^^^^-
+   |                 |
+   |                 help: add the required where clauses: `where Self: 'a, Self: 'b`
+
+error: Missing required bounds on Bar
+  --> $DIR/self-outlives-lint.rs:122:5
+   |
+LL |     type Bar<'b>;
+   |     ^^^^^^^^^^^^-
+   |                 |
+   |                 help: add the required where clauses: `where Self: 'a, Self: 'b`
+
+error: Missing required bounds on Bar
+  --> $DIR/self-outlives-lint.rs:129:5
+   |
+LL |     type Bar<'b>;
+   |     ^^^^^^^^^^^^-
+   |                 |
+   |                 help: add the required where clauses: `where Self: 'b`
+
+error: Missing required bounds on Iterator
+  --> $DIR/self-outlives-lint.rs:143:5
+   |
+LL |     type Iterator<'a>: Iterator<Item = Self::Item<'a>>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                                       |
+   |                                                       help: add the required where clauses: `where Self: 'a`
+
+error: Missing required bounds on Bar
+  --> $DIR/self-outlives-lint.rs:150:5
+   |
+LL |     type Bar<'a, 'b>;
+   |     ^^^^^^^^^^^^^^^^-
+   |                     |
+   |                     help: add the required where clauses: `where 'a: 'b`
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/generic-associated-types/streaming_iterator.rs b/src/test/ui/generic-associated-types/streaming_iterator.rs
index 2feff9f4c6f..f83d4d7b68e 100644
--- a/src/test/ui/generic-associated-types/streaming_iterator.rs
+++ b/src/test/ui/generic-associated-types/streaming_iterator.rs
@@ -5,12 +5,12 @@
 use std::fmt::Display;
 
 trait StreamingIterator {
-    type Item<'a>;
+    type Item<'a> where Self: 'a;
     // Applying the lifetime parameter `'a` to `Self::Item` inside the trait.
     fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
 }
 
-struct Foo<T: StreamingIterator> {
+struct Foo<T: StreamingIterator + 'static> {
     // Applying a concrete lifetime to the constructor outside the trait.
     bar: <T as StreamingIterator>::Item<'static>,
 }
@@ -30,7 +30,7 @@ struct StreamEnumerate<I> {
 }
 
 impl<I: StreamingIterator> StreamingIterator for StreamEnumerate<I> {
-    type Item<'a> = (usize, I::Item<'a>);
+    type Item<'a> where Self: 'a = (usize, I::Item<'a>);
     fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> {
         match self.iter.next() {
             None => None,
@@ -44,7 +44,7 @@ impl<I: StreamingIterator> StreamingIterator for StreamEnumerate<I> {
 }
 
 impl<I: Iterator> StreamingIterator for I {
-    type Item<'a> = <I as Iterator>::Item;
+    type Item<'a> where Self: 'a = <I as Iterator>::Item;
     fn next(&mut self) -> Option<<I as StreamingIterator>::Item<'_>> {
         Iterator::next(self)
     }
diff --git a/src/test/ui/generic-associated-types/variance_constraints.rs b/src/test/ui/generic-associated-types/variance_constraints.rs
index 7bc250ee87b..7d0f7638ac8 100644
--- a/src/test/ui/generic-associated-types/variance_constraints.rs
+++ b/src/test/ui/generic-associated-types/variance_constraints.rs
@@ -3,7 +3,7 @@
 #![feature(generic_associated_types)]
 
 trait A {
-    type B<'a>;
+    type B<'a> where Self: 'a;
 
     fn make_b<'a>(&'a self) -> Self::B<'a>;
 }
diff --git a/src/test/ui/hello2021.rs b/src/test/ui/hello2021.rs
index 738f151b0f6..134d8af5bfb 100644
--- a/src/test/ui/hello2021.rs
+++ b/src/test/ui/hello2021.rs
@@ -1,6 +1,5 @@
 // run-pass
 // edition:2021
-// compile-flags: -Zunstable-options
 
 fn main() {
     println!("hello, 2021");
diff --git a/src/test/ui/issues/issue-44005.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs
index ab3b92142c8..f255eac0c4b 100644
--- a/src/test/ui/issues/issue-44005.rs
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs
@@ -1,3 +1,5 @@
+// check-pass
+
 pub trait Foo<'a> {
     type Bar;
     fn foo(&'a self) -> Self::Bar;
@@ -24,7 +26,6 @@ pub fn catalyst(x: &i32) {
 
 pub fn broken<F: Fn(&i32)>(x: &i32, f: F) {
     uncallable(x, |y| f(y));
-    //~^ type mismatch
 }
 
 fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs
index 24ac566f9df..7c3c72e04cb 100644
--- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs
@@ -77,7 +77,7 @@ where P: Execute + 'static {
 }
 
 fn main() {
-    task(annotate( //~ type mismatch
+    task(annotate(
         //~^ the size
         //~^^ the trait bound
         Annotate::<RefMutFamily<usize>>::new(),
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr
index b13226fef6e..01b14660b65 100644
--- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr
@@ -1,29 +1,3 @@
-error[E0631]: type mismatch in closure arguments
-  --> $DIR/issue-62529-1.rs:80:10
-   |
-LL |       task(annotate(
-   |  _____----_^
-   | |     |
-   | |     required by a bound introduced by this call
-LL | |
-LL | |
-LL | |         Annotate::<RefMutFamily<usize>>::new(),
-LL | |         |value: &mut usize| {
-   | |         ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
-LL | |             *value = 2;
-LL | |         }
-LL | |     ));
-   | |_____^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
-   |
-note: required by a bound in `annotate`
-  --> $DIR/issue-62529-1.rs:44:8
-   |
-LL | fn annotate<F, Q>(_q: Annotate<Q>, func: F) -> impl Execute + 'static
-   |    -------- required by a bound in this
-LL | where
-LL |     F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out) + 'static,
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `annotate`
-
 error[E0277]: the size for values of type `impl Execute` cannot be known at compilation time
   --> $DIR/issue-62529-1.rs:80:10
    |
@@ -73,7 +47,6 @@ LL | fn task<P>(processor: P) -> Task
 LL | where P: Execute + 'static {
    |          ^^^^^^^ required by this bound in `task`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0277, E0631.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs
index 87d1a250f7a..3ced40230f0 100644
--- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs
@@ -1,3 +1,5 @@
+// check-pass
+
 pub trait MyTrait<'a> {
     type Output: 'a;
     fn gimme_value(&self) -> Self::Output;
@@ -23,7 +25,7 @@ where
 
 fn main() {
     let struc = MyStruct;
-    meow(struc, |foo| { //~ type mismatch
+    meow(struc, |foo| {
         println!("{:?}", foo);
     })
 }
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr
deleted file mode 100644
index efc956888ee..00000000000
--- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0631]: type mismatch in closure arguments
-  --> $DIR/issue-70120.rs:26:5
-   |
-LL |     meow(struc, |foo| {
-   |     ^^^^        ----- found signature of `for<'r> fn(&'r usize) -> _`
-   |     |
-   |     expected signature of `for<'any2> fn(<MyStruct as MyTrait<'any2>>::Output) -> _`
-   |
-note: required by a bound in `meow`
-  --> $DIR/issue-70120.rs:18:8
-   |
-LL | fn meow<T, F>(t: T, f: F)
-   |    ---- required by a bound in this
-...
-LL |     F: for<'any2> Fn(<T as MyTrait<'any2>>::Output),
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `meow`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr
new file mode 100644
index 00000000000..119cec1fa95
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr
@@ -0,0 +1,92 @@
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr
new file mode 100644
index 00000000000..69ab446bc7a
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr
@@ -0,0 +1,8 @@
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/issue-71955.rs:42:1
+   |
+LL | fn main() {
+   | ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs
new file mode 100644
index 00000000000..95e3b3d4e1b
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs
@@ -0,0 +1,64 @@
+// ignore-compare-mode-nll
+// revisions: migrate nll
+// [nll]compile-flags: -Zborrowck=mir
+// check-fail
+
+#![feature(rustc_attrs)]
+
+trait Parser<'s> {
+    type Output;
+
+    fn call(&self, input: &'s str) -> (&'s str, Self::Output);
+}
+
+impl<'s, F, T> Parser<'s> for F
+where F: Fn(&'s str) -> (&'s str, T) {
+    type Output = T;
+    fn call(&self, input: &'s str) -> (&'s str, T) {
+        self(input)
+    }
+}
+
+fn foo<F1, F2>(
+    f1: F1,
+    base: &'static str,
+    f2: F2
+)
+where
+    F1: for<'a> Parser<'a>,
+    F2: FnOnce(&<F1 as Parser>::Output) -> bool
+{
+    let s: String = base.to_owned();
+    let str_ref = s.as_ref();
+    let (remaining, produced) = f1.call(str_ref);
+    assert!(f2(&produced));
+    assert_eq!(remaining.len(), 0);
+}
+
+struct Wrapper<'a>(&'a str);
+
+// Because nll currently succeeds and migrate doesn't
+#[rustc_error]
+fn main() {
+    //[nll]~^ fatal
+    fn bar<'a>(s: &'a str) -> (&'a str, &'a str) {
+        (&s[..1], &s[..])
+    }
+
+    fn baz<'a>(s: &'a str) -> (&'a str, Wrapper<'a>) {
+        (&s[..1], Wrapper(&s[..]))
+    }
+
+    foo(bar, "string", |s| s.len() == 5);
+    //[migrate]~^ ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    foo(baz, "string", |s| s.0.len() == 5);
+    //[migrate]~^ ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs
new file mode 100644
index 00000000000..93ccb42684c
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+use std::marker::PhantomData;
+
+trait A<'a> {
+    type B;
+    fn b(self) -> Self::B;
+}
+
+struct T;
+struct S<'a>(PhantomData<&'a ()>);
+
+impl<'a> A<'a> for T {
+    type B = S<'a>;
+    fn b(self) -> Self::B {
+        S(PhantomData)
+    }
+}
+
+fn s<TT, F>(t: TT, f: F)
+where
+    TT: for<'a> A<'a>,
+    F: for<'a> FnOnce(<TT as A<'a>>::B)
+{
+    f(t.b());
+}
+
+fn main() {
+    s(T, |_| {});
+}
diff --git a/src/test/ui/hrtb/issue-90177.rs b/src/test/ui/hrtb/issue-90177.rs
new file mode 100644
index 00000000000..b151a9d3ab6
--- /dev/null
+++ b/src/test/ui/hrtb/issue-90177.rs
@@ -0,0 +1,32 @@
+// check-pass
+
+trait Base<'f> {
+    type Assoc;
+
+    fn do_something(&self);
+}
+
+trait ForAnyLifetime: for<'f> Base<'f> {}
+
+impl<T> ForAnyLifetime for T where T: for<'f> Base<'f> {}
+
+trait CanBeDynamic: ForAnyLifetime + for<'f> Base<'f, Assoc = ()> {}
+
+fn foo(a: &dyn CanBeDynamic) {
+    a.do_something();
+}
+
+struct S;
+
+impl<'a> Base<'a> for S {
+    type Assoc = ();
+
+    fn do_something(&self) {}
+}
+
+impl CanBeDynamic for S {}
+
+fn main() {
+    let s = S;
+    foo(&s);
+}
diff --git a/src/test/ui/issues/issue-44005.stderr b/src/test/ui/issues/issue-44005.stderr
deleted file mode 100644
index 307e444e696..00000000000
--- a/src/test/ui/issues/issue-44005.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0631]: type mismatch in closure arguments
-  --> $DIR/issue-44005.rs:26:5
-   |
-LL |     uncallable(x, |y| f(y));
-   |     ^^^^^^^^^^    -------- found signature of `for<'r> fn(&'r i32) -> _`
-   |     |
-   |     expected signature of `for<'a> fn(<&i32 as Foo<'a>>::Bar) -> _`
-   |
-note: required by a bound in `uncallable`
-  --> $DIR/issue-44005.rs:16:8
-   |
-LL | pub fn uncallable<T, F>(x: T, f: F)
-   |        ---------- required by a bound in this
-...
-LL |     F: for<'a> Fn(<T as Foo<'a>>::Bar),
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `uncallable`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/iterators/into-iter-on-arrays-2021.rs b/src/test/ui/iterators/into-iter-on-arrays-2021.rs
index ec54ed00517..158317efe47 100644
--- a/src/test/ui/iterators/into-iter-on-arrays-2021.rs
+++ b/src/test/ui/iterators/into-iter-on-arrays-2021.rs
@@ -1,6 +1,5 @@
 // check-pass
 // edition:2021
-// compile-flags: -Zunstable-options
 
 use std::array::IntoIter;
 use std::ops::Deref;
diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed b/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed
new file mode 100644
index 00000000000..0bc889ee721
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed
@@ -0,0 +1,9 @@
+// run-rustfix
+
+pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr b/src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr
new file mode 100644
index 00000000000..a5bc7450bbf
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr
@@ -0,0 +1,29 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-90170-elision-mismatch.rs:3:40
+   |
+LL | pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); }
+   |                        -        -      ^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |                        |        |
+   |                        |        let's call the lifetime of this reference `'1`
+   |                        let's call the lifetime of this reference `'2`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-90170-elision-mismatch.rs:5:44
+   |
+LL | pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); }
+   |                         -           -      ^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |                         |           |
+   |                         |           let's call the lifetime of this reference `'1`
+   |                         let's call the lifetime of this reference `'2`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-90170-elision-mismatch.rs:7:63
+   |
+LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); }
+   |                                               -        -      ^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |                                               |        |
+   |                                               |        let's call the lifetime of this reference `'1`
+   |                                               let's call the lifetime of this reference `'2`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs b/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs
new file mode 100644
index 00000000000..1d6573c00ad
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs
@@ -0,0 +1,9 @@
+// run-rustfix
+
+pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr b/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr
new file mode 100644
index 00000000000..7fa092ca220
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr
@@ -0,0 +1,45 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/issue-90170-elision-mismatch.rs:3:47
+   |
+LL | pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); }
+   |                        ---      ---           ^ ...but data from `y` flows into `x` here
+   |                                 |
+   |                                 these two types are declared with different lifetimes...
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+   |           ++++              ++          ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/issue-90170-elision-mismatch.rs:5:51
+   |
+LL | pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); }
+   |                         ------      ---           ^ ...but data from `y` flows into `x` here
+   |                                     |
+   |                                     these two types are declared with different lifetimes...
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+   |            ++++              ~~          ++
+
+error[E0623]: lifetime mismatch
+  --> $DIR/issue-90170-elision-mismatch.rs:7:70
+   |
+LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); }
+   |                                               ---      ---           ^ ...but data from `y` flows into `x` here
+   |                                                        |
+   |                                                        these two types are declared with different lifetimes...
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+   |                                                ++          ++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr
index 0aff80c6fbd..5c793636778 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr
@@ -5,6 +5,12 @@ LL | fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) {
    |                                   ---           --- these two types are declared with different lifetimes...
 LL |     *v = x;
    |          ^ ...but data from `x` flows here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(&mut (ref mut v, w): &mut (&'a u8, &u8), x: &'a u8) {
+   |       ++++                             ++               ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr
index 2e5ff6782d3..1a7b4fca1ba 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr
@@ -5,6 +5,12 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
    |                     ---                 --- these two types are declared with different lifetimes...
 LL |     z.push((x,y));
    |             ^ ...but data flows into `z` here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(z: &mut Vec<(&'a u8,&u8)>, (x, y): (&'a u8, &u8)) {
+   |       ++++               ++                     ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ex3-both-anon-regions-3.rs:2:15
@@ -13,6 +19,12 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
    |                         ---                  --- these two types are declared with different lifetimes...
 LL |     z.push((x,y));
    |               ^ ...but data flows into `z` here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(z: &mut Vec<(&u8,&'a u8)>, (x, y): (&u8, &'a u8)) {
+   |       ++++                   ++                      ++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr
index d2cc3dba6a4..6ed3528bb9f 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr
@@ -5,6 +5,12 @@ LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) {
    |                               ---      --- these two types are declared with different lifetimes...
 LL |   y.push(z);
    |          ^ ...but data from `z` flows into `y` here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) {
+   |       ++++                         ++          ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr
index 2acc4eaf60f..ede1631db27 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr
@@ -5,6 +5,12 @@ LL | fn foo(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
    |                     ---  --- these two types are declared with different lifetimes...
 LL |   y.push(z);
    |          ^ ...but data from `z` flows into `y` here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(x:Box<dyn Fn(&'a u8, &'a u8)> , y: Vec<&u8>, z: &u8) {
+   |       ++++               ++      ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr
index b2784827672..cf405c0de3f 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr
@@ -5,6 +5,12 @@ LL | fn foo(x: &mut Vec<&u8>, y: &u8) {
    |                    ---      --- these two types are declared with different lifetimes...
 LL |     x.push(y);
    |            ^ ...but data from `y` flows into `x` here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) {
+   |       ++++              ++          ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs b/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs
index 3fab9148392..3a3d81176d6 100644
--- a/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs
+++ b/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs
@@ -1,6 +1,6 @@
 // --force-warn $LINT causes $LINT (which is deny-by-default) to warn
 // despite $LINT being allowed on command line
-// compile-flags: -A const_err --force-warn const_err -Zunstable-options
+// compile-flags: -A const_err --force-warn const_err
 // check-pass
 
 const C: i32 = 1 / 0;
diff --git a/src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs b/src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs
index 4eb05b538b0..9736027452a 100644
--- a/src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs
+++ b/src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs
@@ -1,6 +1,6 @@
 // --force-warn $LINT_GROUP causes $LINT (which is warn-by-default) to warn
 // despite $LINT being allowed on command line
-// compile-flags: -A bare-trait-objects --force-warn rust-2018-idioms -Zunstable-options
+// compile-flags: -A bare-trait-objects --force-warn rust-2018-idioms
 // check-pass
 
 pub trait SomeTrait {}
diff --git a/src/test/ui/lint/force-warn/warn-by-default-lint-two-modules.rs b/src/test/ui/lint/force-warn/warn-by-default-lint-two-modules.rs
index d2cb3417be6..267e7b45f0c 100644
--- a/src/test/ui/lint/force-warn/warn-by-default-lint-two-modules.rs
+++ b/src/test/ui/lint/force-warn/warn-by-default-lint-two-modules.rs
@@ -1,6 +1,6 @@
 // --force-warn $LINT causes $LINT (which is warn-by-default) to warn
 // despite being allowed in one submodule (but not the other)
-// compile-flags: --force-warn dead_code -Zunstable-options
+// compile-flags: --force-warn dead_code
 // check-pass
 
 mod one {
diff --git a/src/test/ui/lint/force-warn/warnings-lint-group.rs b/src/test/ui/lint/force-warn/warnings-lint-group.rs
index fa25a1f8a84..d1d4f5602f2 100644
--- a/src/test/ui/lint/force-warn/warnings-lint-group.rs
+++ b/src/test/ui/lint/force-warn/warnings-lint-group.rs
@@ -1,5 +1,5 @@
 // --force-warn warnings is an error
-// compile-flags: --force-warn warnings -Zunstable-options
+// compile-flags: --force-warn warnings
 // error-pattern: `warnings` lint group is not supported
 
 fn main() {}
diff --git a/src/test/ui/lint/force-warn/warnings-lint-group.stderr b/src/test/ui/lint/force-warn/warnings-lint-group.stderr
index 03f5788b527..1faeed33704 100644
--- a/src/test/ui/lint/force-warn/warnings-lint-group.stderr
+++ b/src/test/ui/lint/force-warn/warnings-lint-group.stderr
@@ -2,8 +2,6 @@ error[E0602]: `warnings` lint group is not supported with ´--force-warn´
 
 error[E0602]: `warnings` lint group is not supported with ´--force-warn´
 
-error[E0602]: `warnings` lint group is not supported with ´--force-warn´
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0602`.
diff --git a/src/test/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs b/src/test/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs
new file mode 100644
index 00000000000..425e2703c94
--- /dev/null
+++ b/src/test/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs
@@ -0,0 +1,9 @@
+// check-pass
+// Allowing the code lint should work without warning and
+// the text flow char in the comment should be ignored.
+
+#![allow(text_direction_codepoint_in_comment)]
+
+fn main() {
+    // U+2066 LEFT-TO-RIGHT ISOLATE follows:⁦⁦
+}
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.fixed b/src/test/ui/lint/unused_parens_json_suggestion.fixed
index 15ee19755bf..c4004540467 100644
--- a/src/test/ui/lint/unused_parens_json_suggestion.fixed
+++ b/src/test/ui/lint/unused_parens_json_suggestion.fixed
@@ -1,4 +1,4 @@
-// compile-flags: --error-format json -Zunstable-options
+// compile-flags: --error-format json
 // run-rustfix
 
 // The output for humans should just highlight the whole span without showing
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.rs b/src/test/ui/lint/unused_parens_json_suggestion.rs
index d72df21e09a..962c8bdd7d7 100644
--- a/src/test/ui/lint/unused_parens_json_suggestion.rs
+++ b/src/test/ui/lint/unused_parens_json_suggestion.rs
@@ -1,4 +1,4 @@
-// compile-flags: --error-format json -Zunstable-options
+// compile-flags: --error-format json
 // run-rustfix
 
 // The output for humans should just highlight the whole span without showing
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.stderr b/src/test/ui/lint/unused_parens_json_suggestion.stderr
index 498c25d2e1c..169fb824021 100644
--- a/src/test/ui/lint/unused_parens_json_suggestion.stderr
+++ b/src/test/ui/lint/unused_parens_json_suggestion.stderr
@@ -1,4 +1,4 @@
-{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":597,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));
+{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":577,"byte_end":578,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));
   --> $DIR/unused_parens_json_suggestion.rs:16:14
    |
 LL |     let _a = (1 / (2 + 3));
diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed b/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed
index 1d891d328dd..8a57cd57385 100644
--- a/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed
+++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed
@@ -1,4 +1,4 @@
-// compile-flags: --error-format json -Zunstable-options
+// compile-flags: --error-format json
 // run-rustfix
 
 // The output for humans should just highlight the whole span without showing
diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.rs b/src/test/ui/lint/unused_parens_remove_json_suggestion.rs
index 494cd184506..952332d54e9 100644
--- a/src/test/ui/lint/unused_parens_remove_json_suggestion.rs
+++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.rs
@@ -1,4 +1,4 @@
-// compile-flags: --error-format json -Zunstable-options
+// compile-flags: --error-format json
 // run-rustfix
 
 // The output for humans should just highlight the whole span without showing
diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr
index 08291b10fcc..43367aaa911 100644
--- a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr
+++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr
@@ -1,4 +1,4 @@
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":501,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":"    if (_b) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":481,"byte_end":482,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":"    if (_b) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:17:8
    |
 LL |     if (_b) {
@@ -16,7 +16,7 @@ LL +     if _b {
    | 
 
 "}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":632,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":"    if(c) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":612,"byte_end":613,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":"    if(c) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:28:7
    |
 LL |     if(c) {
@@ -29,7 +29,7 @@ LL +     if c {
    | 
 
 "}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":712,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":"    if (c){
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":692,"byte_end":693,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":"    if (c){
   --> $DIR/unused_parens_remove_json_suggestion.rs:32:8
    |
 LL |     if (c){
@@ -42,7 +42,7 @@ LL +     if c {
    | 
 
 "}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
   --> $DIR/unused_parens_remove_json_suggestion.rs:36:11
    |
 LL |     while (false && true){
@@ -55,7 +55,7 @@ LL +     while false && true {
    | 
 
 "}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":822,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":"        if (c) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":802,"byte_end":803,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":"        if (c) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:37:12
    |
 LL |         if (c) {
@@ -68,7 +68,7 @@ LL +         if c {
    | 
 
 "}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":919,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":"    while(true && false) {
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":899,"byte_end":900,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":"    while(true && false) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:43:10
    |
 LL |     while(true && false) {
@@ -81,7 +81,7 @@ LL +     while true && false {
    | 
 
 "}
-{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":988,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":"        for _ in (0 .. 3){
+{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":968,"byte_end":969,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":"        for _ in (0 .. 3){
   --> $DIR/unused_parens_remove_json_suggestion.rs:44:18
    |
 LL |         for _ in (0 .. 3){
@@ -94,7 +94,7 @@ LL +         for _ in 0 .. 3 {
    | 
 
 "}
-{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1089,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":"    for _ in (0 .. 3) {
+{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1069,"byte_end":1070,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":"    for _ in (0 .. 3) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:49:14
    |
 LL |     for _ in (0 .. 3) {
@@ -107,7 +107,7 @@ LL +     for _ in 0 .. 3 {
    | 
 
 "}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1148,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":"        while (true && false) {
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1128,"byte_end":1129,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":"        while (true && false) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:50:15
    |
 LL |         while (true && false) {
diff --git a/src/test/ui/matches2021.rs b/src/test/ui/matches2021.rs
index f5497c1d16d..9143a8cdd59 100644
--- a/src/test/ui/matches2021.rs
+++ b/src/test/ui/matches2021.rs
@@ -1,6 +1,5 @@
 // run-pass
 // edition:2021
-// compile-flags: -Zunstable-options
 
 // regression test for https://github.com/rust-lang/rust/pull/85678
 
diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs b/src/test/ui/mir-dataflow/indirect-mutation-offset.rs
deleted file mode 100644
index 374a9f75a13..00000000000
--- a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-// compile-flags: -Zunleash-the-miri-inside-of-you
-
-// This test demonstrates a shortcoming of the `MaybeMutBorrowedLocals` analysis. It does not
-// handle code that takes a reference to one field of a struct, then use pointer arithmetic to
-// transform it to another field of that same struct that may have interior mutability. For now,
-// this is UB, but this may change in the future. See [rust-lang/unsafe-code-guidelines#134].
-//
-// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
-
-#![feature(core_intrinsics, rustc_attrs, const_raw_ptr_deref)]
-
-use std::cell::UnsafeCell;
-use std::intrinsics::rustc_peek;
-
-#[repr(C)]
-struct PartialInteriorMut {
-    zst: [i32; 0],
-    cell: UnsafeCell<i32>,
-}
-
-#[rustc_mir(rustc_peek_indirectly_mutable,stop_after_dataflow)]
-const BOO: i32 = {
-    let x = PartialInteriorMut {
-        zst: [],
-        cell: UnsafeCell::new(0),
-    };
-
-    let p_zst: *const _ = &x.zst ; // Doesn't cause `x` to get marked as indirectly mutable.
-
-    let rmut_cell = unsafe {
-        // Take advantage of the fact that `zst` and `cell` are at the same location in memory.
-        // This trick would work with any size type if miri implemented `ptr::offset`.
-        let p_cell = p_zst as *const UnsafeCell<i32>;
-
-        let pmut_cell = (*p_cell).get();
-        &mut *pmut_cell
-    };
-
-    *rmut_cell = 42;  // Mutates `x` indirectly even though `x` is not marked indirectly mutable!!!
-    let val = *rmut_cell;
-    rustc_peek(x); //~ ERROR rustc_peek: bit not set
-
-    val
-};
-
-fn main() {
-    println!("{}", BOO);
-}
diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr b/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr
deleted file mode 100644
index 1d5287c15ab..00000000000
--- a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: rustc_peek: bit not set
-  --> $DIR/indirect-mutation-offset.rs:41:5
-   |
-LL |     rustc_peek(x);
-   |     ^^^^^^^^^^^^^
-
-error: stop_after_dataflow ended compilation
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs
index f926eee9d92..ec8666f93f0 100644
--- a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs
+++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs
@@ -1,5 +1,6 @@
 // aux-crate:priv:priv_dep=priv_dep.rs
 // aux-build:pub_dep.rs
+// compile-flags: -Zunstable-options
 #![deny(exported_private_dependencies)]
 
 // This crate is a private dependency
diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr
index e6b4d33f103..f64b8569015 100644
--- a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr
+++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr
@@ -1,23 +1,23 @@
 error: type `OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:20:5
+  --> $DIR/pub-priv1.rs:21:5
    |
 LL |     pub field: OtherType,
    |     ^^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/pub-priv1.rs:3:9
+  --> $DIR/pub-priv1.rs:4:9
    |
 LL | #![deny(exported_private_dependencies)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: type `OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:27:5
+  --> $DIR/pub-priv1.rs:28:5
    |
 LL |     pub fn pub_fn(param: OtherType) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:34:5
+  --> $DIR/pub-priv1.rs:35:5
    |
 LL |     type Foo: OtherTrait;
    |     ^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/proc-macro/auxiliary/api/parse.rs b/src/test/ui/proc-macro/auxiliary/api/parse.rs
index 93551ebaf82..6186b941ef6 100644
--- a/src/test/ui/proc-macro/auxiliary/api/parse.rs
+++ b/src/test/ui/proc-macro/auxiliary/api/parse.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-linelength
+
 use proc_macro::Literal;
 
 pub fn test() {
@@ -8,6 +10,14 @@ pub fn test() {
 fn test_display_literal() {
     assert_eq!(Literal::isize_unsuffixed(-10).to_string(), "-10");
     assert_eq!(Literal::isize_suffixed(-10).to_string(), "-10isize");
+    assert_eq!(Literal::f32_unsuffixed(-10.0).to_string(), "-10.0");
+    assert_eq!(Literal::f32_suffixed(-10.0).to_string(), "-10f32");
+    assert_eq!(Literal::f64_unsuffixed(-10.0).to_string(), "-10.0");
+    assert_eq!(Literal::f64_suffixed(-10.0).to_string(), "-10f64");
+    assert_eq!(
+        Literal::f64_unsuffixed(1e100).to_string(),
+        "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0",
+    );
 }
 
 fn test_parse_literal() {
diff --git a/src/test/ui/rust-2021/prelude2021.rs b/src/test/ui/rust-2021/prelude2021.rs
index 3a9fd693228..a63b6fcf262 100644
--- a/src/test/ui/rust-2021/prelude2021.rs
+++ b/src/test/ui/rust-2021/prelude2021.rs
@@ -1,6 +1,5 @@
 // check-pass
 // edition:2021
-// compile-flags: -Zunstable-options
 
 fn main() {
     let _: u16 = 123i32.try_into().unwrap();
diff --git a/src/test/ui/rust-2021/reserved-prefixes-migration.fixed b/src/test/ui/rust-2021/reserved-prefixes-migration.fixed
index e026f01e93f..eed2f313abe 100644
--- a/src/test/ui/rust-2021/reserved-prefixes-migration.fixed
+++ b/src/test/ui/rust-2021/reserved-prefixes-migration.fixed
@@ -1,6 +1,6 @@
 // check-pass
 // run-rustfix
-// compile-flags: -Z unstable-options --edition 2018
+// edition:2018
 
 #![warn(rust_2021_prefixes_incompatible_syntax)]
 
diff --git a/src/test/ui/rust-2021/reserved-prefixes-migration.rs b/src/test/ui/rust-2021/reserved-prefixes-migration.rs
index d24f2963480..0565db793df 100644
--- a/src/test/ui/rust-2021/reserved-prefixes-migration.rs
+++ b/src/test/ui/rust-2021/reserved-prefixes-migration.rs
@@ -1,6 +1,6 @@
 // check-pass
 // run-rustfix
-// compile-flags: -Z unstable-options --edition 2018
+// edition:2018
 
 #![warn(rust_2021_prefixes_incompatible_syntax)]
 
diff --git a/src/test/ui/suggestions/undeclared-module-alloc.rs b/src/test/ui/suggestions/undeclared-module-alloc.rs
new file mode 100644
index 00000000000..1defa1cef28
--- /dev/null
+++ b/src/test/ui/suggestions/undeclared-module-alloc.rs
@@ -0,0 +1,5 @@
+// edition:2018
+
+use alloc::rc::Rc; //~ ERROR failed to resolve: use of undeclared crate or module `alloc`
+
+fn main() {}
diff --git a/src/test/ui/suggestions/undeclared-module-alloc.stderr b/src/test/ui/suggestions/undeclared-module-alloc.stderr
new file mode 100644
index 00000000000..39169dfa9f7
--- /dev/null
+++ b/src/test/ui/suggestions/undeclared-module-alloc.stderr
@@ -0,0 +1,11 @@
+error[E0433]: failed to resolve: use of undeclared crate or module `alloc`
+  --> $DIR/undeclared-module-alloc.rs:3:5
+   |
+LL | use alloc::rc::Rc;
+   |     ^^^^^ use of undeclared crate or module `alloc`
+   |
+   = help: add `extern crate alloc` to use the `alloc` crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr
index 76c14ccc14b..8976da01e73 100644
--- a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr
+++ b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr
@@ -5,6 +5,12 @@ LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); }
    |                    ------      ------           ^ ...but data from `y` flows into `x` here
    |                                |
    |                                these two types are declared with different lifetimes...
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+   |       ++++              ~~          ~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unsized/unchanged-param.rs b/src/test/ui/unsized/unchanged-param.rs
index 83199e8112e..93c7af68ac3 100644
--- a/src/test/ui/unsized/unchanged-param.rs
+++ b/src/test/ui/unsized/unchanged-param.rs
@@ -1,4 +1,3 @@
-#![feature(relaxed_struct_unsize)]
 // run-pass
 // Test that we allow unsizing even if there is an unchanged param in the
 // field getting unsized.
diff --git a/src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs b/src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs
index 9339a004d3b..6ac558974d0 100644
--- a/src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs
+++ b/src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs
@@ -1,7 +1,7 @@
 // --extern-location with a raw reference
 
 // aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar
+// compile-flags:--extern-location bar -Zunstable-options
 
 #![warn(unused_crate_dependencies)]
 
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 6c1bc24b8b49d4bc965f67d7037906dc199c72b
+Subproject 94ca096afbf25f670e76e07dca754fcfe27134b
diff --git a/src/tools/clippy/.cargo/config b/src/tools/clippy/.cargo/config.toml
index 688473f2f9b..688473f2f9b 100644
--- a/src/tools/clippy/.cargo/config
+++ b/src/tools/clippy/.cargo/config.toml
diff --git a/src/tools/clippy/.github/deploy.sh b/src/tools/clippy/.github/deploy.sh
index a3c57232f55..34225a54029 100644
--- a/src/tools/clippy/.github/deploy.sh
+++ b/src/tools/clippy/.github/deploy.sh
@@ -13,7 +13,8 @@ cp util/gh-pages/lints.json out/master
 if [[ -n $TAG_NAME ]]; then
   echo "Save the doc for the current tag ($TAG_NAME) and point stable/ to it"
   cp -Tr out/master "out/$TAG_NAME"
-  ln -sf "$TAG_NAME" out/stable
+  rm -f out/stable
+  ln -s "$TAG_NAME" out/stable
 fi
 
 if [[ $BETA = "true" ]]; then
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 3b4c687209e..85a6a6be8b7 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6,11 +6,162 @@ document.
 
 ## Unreleased / In Rust Nightly
 
-[7bfc26e...master](https://github.com/rust-lang/rust-clippy/compare/7bfc26e...master)
+[b7f3f7f...master](https://github.com/rust-lang/rust-clippy/compare/b7f3f7f...master)
+
+## Rust 1.57
+
+Current beta, release 2021-12-02
+
+[7bfc26e...b7f3f7f](https://github.com/rust-lang/rust-clippy/compare/7bfc26e...b7f3f7f)
+
+### New Lints
+
+* [`negative_feature_names`]
+  [#7539](https://github.com/rust-lang/rust-clippy/pull/7539)
+* [`redundant_feature_names`]
+  [#7539](https://github.com/rust-lang/rust-clippy/pull/7539)
+* [`mod_module_files`]
+  [#7543](https://github.com/rust-lang/rust-clippy/pull/7543)
+* [`self_named_module_files`]
+  [#7543](https://github.com/rust-lang/rust-clippy/pull/7543)
+* [`manual_split_once`]
+  [#7565](https://github.com/rust-lang/rust-clippy/pull/7565)
+* [`derivable_impls`]
+  [#7570](https://github.com/rust-lang/rust-clippy/pull/7570)
+* [`needless_option_as_deref`]
+  [#7596](https://github.com/rust-lang/rust-clippy/pull/7596)
+* [`iter_not_returning_iterator`]
+  [#7610](https://github.com/rust-lang/rust-clippy/pull/7610)
+* [`same_name_method`]
+  [#7653](https://github.com/rust-lang/rust-clippy/pull/7653)
+* [`manual_assert`] [#7669](https://github.com/rust-lang/rust-clippy/pull/7669)
+* [`non_send_fields_in_send_ty`]
+  [#7709](https://github.com/rust-lang/rust-clippy/pull/7709)
+* [`equatable_if_let`]
+  [#7762](https://github.com/rust-lang/rust-clippy/pull/7762)
+
+### Moves and Deprecations
+
+* Move [`shadow_unrelated`] to `restriction`
+  [#7338](https://github.com/rust-lang/rust-clippy/pull/7338)
+* Move [`option_if_let_else`] to `nursery`
+  [#7568](https://github.com/rust-lang/rust-clippy/pull/7568)
+* Move [`branches_sharing_code`] to `nursery`
+  [#7595](https://github.com/rust-lang/rust-clippy/pull/7595)
+* Rename `if_let_some_result` to [`match_result_ok`] which now also handles
+  `while let` cases [#7608](https://github.com/rust-lang/rust-clippy/pull/7608)
+* Move [`many_single_char_names`] to `pedantic`
+  [#7671](https://github.com/rust-lang/rust-clippy/pull/7671)
+* Move [`float_cmp`] to `pedantic`
+  [#7692](https://github.com/rust-lang/rust-clippy/pull/7692)
+* Rename `box_vec` to [`box_collection`] and lint on more general cases
+  [#7693](https://github.com/rust-lang/rust-clippy/pull/7693)
+* Uplift `invalid_atomic_ordering` to rustc
+  [rust-lang/rust#84039](https://github.com/rust-lang/rust/pull/84039)
+
+### Enhancements
+
+* Rewrite the `shadow*` lints, so that they find a lot more shadows and are not
+  limited to certain patterns
+  [#7338](https://github.com/rust-lang/rust-clippy/pull/7338)
+* The `avoid-breaking-exported-api` configuration now also works for
+  [`box_collection`], [`redundant_allocation`], [`rc_buffer`], [`vec_box`],
+  [`option_option`], [`linkedlist`], [`rc_mutex`]
+  [#7560](https://github.com/rust-lang/rust-clippy/pull/7560)
+* [`unnecessary_unwrap`]: Now also checks for `expect`s
+  [#7584](https://github.com/rust-lang/rust-clippy/pull/7584)
+* [`disallowed_method`]: Allow adding a reason that will be displayed with the
+  lint message
+  [#7621](https://github.com/rust-lang/rust-clippy/pull/7621)
+* [`approx_constant`]: Now checks the MSRV for `LOG10_2` and `LOG2_10`
+  [#7629](https://github.com/rust-lang/rust-clippy/pull/7629)
+* [`approx_constant`]: Add `TAU`
+  [#7642](https://github.com/rust-lang/rust-clippy/pull/7642)
+* [`needless_borrow`]: Now also lints on needless mutable borrows
+  [#7657](https://github.com/rust-lang/rust-clippy/pull/7657)
+* [`missing_safety_doc`]: Now also lints on unsafe traits
+  [#7734](https://github.com/rust-lang/rust-clippy/pull/7734)
+
+### False Positive Fixes
+
+* [`manual_map`]: No longer lints when the option is borrowed in the match and
+  also consumed in the arm
+  [#7531](https://github.com/rust-lang/rust-clippy/pull/7531)
+* [`filter_next`]: No longer lints if `filter` method is not the
+  `Iterator::filter` method
+  [#7562](https://github.com/rust-lang/rust-clippy/pull/7562)
+* [`manual_flatten`]: No longer lints if expression is used after `if let`
+  [#7566](https://github.com/rust-lang/rust-clippy/pull/7566)
+* [`option_if_let_else`]: Multiple fixes
+  [#7573](https://github.com/rust-lang/rust-clippy/pull/7573)
+    * `break` and `continue` statements local to the would-be closure are
+      allowed
+    * Don't lint in const contexts
+    * Don't lint when yield expressions are used
+    * Don't lint when the captures made by the would-be closure conflict with
+      the other branch
+    * Don't lint when a field of a local is used when the type could be
+      potentially moved from
+    * In some cases, don't lint when scrutinee expression conflicts with the
+      captures of the would-be closure
+* [`redundant_allocation`]: No longer lints on `Box<Box<dyn T>>` which replaces
+  wide pointers with thin pointers
+  [#7592](https://github.com/rust-lang/rust-clippy/pull/7592)
+* [`bool_assert_comparison`]: No longer lints on types that do not implement the
+  `Not` trait with `Output = bool`
+  [#7605](https://github.com/rust-lang/rust-clippy/pull/7605)
+* [`mut_range_bound`]: No longer lints on range bound mutations, that are
+  immediately followed by a `break;`
+  [#7607](https://github.com/rust-lang/rust-clippy/pull/7607)
+* [`mutable_key_type`]: Improve accuracy and document remaining false positives
+  and false negatives
+  [#7640](https://github.com/rust-lang/rust-clippy/pull/7640)
+* [`redundant_closure`]: Rewrite the lint to fix various false positives and
+  false negatives [#7661](https://github.com/rust-lang/rust-clippy/pull/7661)
+* [`large_enum_variant`]: No longer wrongly identifies the second largest
+  variant [#7677](https://github.com/rust-lang/rust-clippy/pull/7677)
+* [`needless_return`]: No longer lints on let-else expressions
+  [#7685](https://github.com/rust-lang/rust-clippy/pull/7685)
+* [`suspicious_else_formatting`]: No longer lints in proc-macros
+  [#7707](https://github.com/rust-lang/rust-clippy/pull/7707)
+* [`excessive_precision`]: No longer lints when in some cases the float was
+  already written in the shortest form
+  [#7722](https://github.com/rust-lang/rust-clippy/pull/7722)
+* [`doc_markdown`]: No longer lints on intra-doc links
+  [#7772](https://github.com/rust-lang/rust-clippy/pull/7772)
+
+### Suggestion Fixes/Improvements
+
+* [`unnecessary_operation`]: Recommend using an `assert!` instead of using a
+  function call in an indexing operation
+  [#7453](https://github.com/rust-lang/rust-clippy/pull/7453)
+* [`manual_split_once`]: Produce semantically equivalent suggestion when
+  `rsplitn` is used [#7663](https://github.com/rust-lang/rust-clippy/pull/7663)
+* [`while_let_on_iterator`]: Produce correct suggestion when using `&mut`
+  [#7690](https://github.com/rust-lang/rust-clippy/pull/7690)
+* [`manual_assert`]: No better handles complex conditions
+  [#7741](https://github.com/rust-lang/rust-clippy/pull/7741)
+* Correctly handle signs in exponents in numeric literals lints
+  [#7747](https://github.com/rust-lang/rust-clippy/pull/7747)
+* [`suspicious_map`]: Now also suggests to use `inspect` as an alternative
+  [#7770](https://github.com/rust-lang/rust-clippy/pull/7770)
+* Drop exponent from suggestion if it is 0 in numeric literals lints
+  [#7774](https://github.com/rust-lang/rust-clippy/pull/7774)
+
+### ICE Fixes
+
+* [`implicit_hasher`]
+  [#7761](https://github.com/rust-lang/rust-clippy/pull/7761)
+
+### Others
+
+* Clippy now uses the 2021
+  [Edition!](https://www.youtube.com/watch?v=q0aNduqb2Ro)
+  [#7664](https://github.com/rust-lang/rust-clippy/pull/7664)
 
 ## Rust 1.56
 
-Current beta, release 2021-10-21
+Current stable, released 2021-10-21
 
 [74d1561...7bfc26e](https://github.com/rust-lang/rust-clippy/compare/74d1561...7bfc26e)
 
@@ -74,13 +225,9 @@ Current beta, release 2021-10-21
 * [`unnested_or_patterns`]: Removed `or_patterns` feature gate in the code
   example [#7507](https://github.com/rust-lang/rust-clippy/pull/7507)
 
-### New Lints
-
-* Renamed Lint: `if_let_some_result` is now called [`match_result_ok`]. Now also handles `while let` case.
-
 ## Rust 1.55
 
-Current stable, released 2021-09-09
+Released 2021-09-09
 
 [3ae8faf...74d1561](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...74d1561)
 
@@ -2748,7 +2895,6 @@ Released 2018-09-13
 [`if_let_redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_redundant_pattern_matching
 [`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_panic`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic
 [`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
@@ -2806,6 +2952,7 @@ Released 2018-09-13
 [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal
 [`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports
 [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
+[`manual_assert`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_assert
 [`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
 [`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map
 [`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map
@@ -2976,6 +3123,7 @@ Released 2018-09-13
 [`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors
 [`self_named_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_module_files
 [`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
+[`separated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#separated_literal_suffix
 [`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse
 [`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse
 [`shadow_same`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_same
@@ -3000,6 +3148,7 @@ Released 2018-09-13
 [`string_extend_chars`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_extend_chars
 [`string_from_utf8_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_from_utf8_as_bytes
 [`string_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_as_bytes
+[`string_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_slice
 [`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string
 [`strlen_on_c_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#strlen_on_c_strings
 [`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools
@@ -3046,6 +3195,7 @@ Released 2018-09-13
 [`uninit_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_vec
 [`unit_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg
 [`unit_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_cmp
+[`unit_hash`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_hash
 [`unit_return_expecting_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_return_expecting_ord
 [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
 [`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map
diff --git a/src/tools/clippy/CONTRIBUTING.md b/src/tools/clippy/CONTRIBUTING.md
index 4273fda4e64..97ff31b4bc5 100644
--- a/src/tools/clippy/CONTRIBUTING.md
+++ b/src/tools/clippy/CONTRIBUTING.md
@@ -262,7 +262,9 @@ to be run inside the `rust` directory):
 2. Checkout the commit from the latest available nightly. You can get it using `rustup check`.
 3. Sync the changes to the rust-copy of Clippy to your Clippy fork:
     ```bash
-    # Make sure to change `your-github-name` to your github name in the following command
+    # Make sure to change `your-github-name` to your github name in the following command. Also be
+    # sure to either use a net-new branch, e.g. `sync-from-rust`, or delete the branch beforehand
+    # because changes cannot be fast forwarded
     git subtree push -P src/tools/clippy git@github.com:your-github-name/rust-clippy sync-from-rust
     ```
 
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index ed7fb144013..602877bb9d6 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -22,13 +22,13 @@ path = "src/driver.rs"
 
 [dependencies]
 clippy_lints = { version = "0.1", path = "clippy_lints" }
-semver = "0.11"
+semver = "1.0"
 rustc_tools_util = { version = "0.2", path = "rustc_tools_util" }
 tempfile = { version = "3.2", optional = true }
 
 [dev-dependencies]
-cargo_metadata = "0.12"
-compiletest_rs = { version = "0.7", features = ["tmp"] }
+cargo_metadata = "0.14"
+compiletest_rs = { version = "0.7.1", features = ["tmp"] }
 tester = "0.9"
 regex = "1.5"
 # This is used by the `collect-metadata` alias.
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index 25320907bb4..43a478ee77d 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -42,7 +42,8 @@ pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str
     };
 
     create_lint(&lint, msrv).context("Unable to create lint implementation")?;
-    create_test(&lint).context("Unable to create a test for the new lint")
+    create_test(&lint).context("Unable to create a test for the new lint")?;
+    add_lint(&lint, msrv).context("Unable to add lint to clippy_lints/src/lib.rs")
 }
 
 fn create_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
@@ -80,6 +81,33 @@ fn create_test(lint: &LintData<'_>) -> io::Result<()> {
     }
 }
 
+fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
+    let path = "clippy_lints/src/lib.rs";
+    let mut lib_rs = fs::read_to_string(path).context("reading")?;
+
+    let comment_start = lib_rs.find("// add lints here,").expect("Couldn't find comment");
+
+    let new_lint = if enable_msrv {
+        format!(
+            "store.register_{lint_pass}_pass(move || Box::new({module_name}::{camel_name}::new(msrv)));\n    ",
+            lint_pass = lint.pass,
+            module_name = lint.name,
+            camel_name = to_camel_case(lint.name),
+        )
+    } else {
+        format!(
+            "store.register_{lint_pass}_pass(|| Box::new({module_name}::{camel_name}));\n    ",
+            lint_pass = lint.pass,
+            module_name = lint.name,
+            camel_name = to_camel_case(lint.name),
+        )
+    };
+
+    lib_rs.insert_str(comment_start, &new_lint);
+
+    fs::write(path, lib_rs).context("writing")
+}
+
 fn write_file<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> {
     fn inner(path: &Path, contents: &[u8]) -> io::Result<()> {
         OpenOptions::new()
@@ -151,7 +179,6 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
     };
 
     let lint_name = lint.name;
-    let pass_name = lint.pass;
     let category = lint.category;
     let name_camel = to_camel_case(lint.name);
     let name_upper = lint_name.to_uppercase();
@@ -228,18 +255,14 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
                     extract_msrv_attr!({context_import});
                 }}
 
-                // TODO: Register the lint pass in `clippy_lints/src/lib.rs`,
-                //       e.g. store.register_{pass_name}_pass(move || Box::new({module_name}::{name_camel}::new(msrv)));
                 // TODO: Add MSRV level to `clippy_utils/src/msrvs.rs` if needed.
                 // TODO: Add MSRV test to `tests/ui/min_rust_version_attr.rs`.
                 // TODO: Update msrv config comment in `clippy_lints/src/utils/conf.rs`
             "},
             pass_type = pass_type,
             pass_lifetimes = pass_lifetimes,
-            pass_name = pass_name,
             name_upper = name_upper,
             name_camel = name_camel,
-            module_name = lint_name,
             context_import = context_import,
         )
     } else {
@@ -248,16 +271,11 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
                 declare_lint_pass!({name_camel} => [{name_upper}]);
 
                 impl {pass_type}{pass_lifetimes} for {name_camel} {{}}
-                //
-                // TODO: Register the lint pass in `clippy_lints/src/lib.rs`,
-                //       e.g. store.register_{pass_name}_pass(|| Box::new({module_name}::{name_camel}));
             "},
             pass_type = pass_type,
             pass_lifetimes = pass_lifetimes,
-            pass_name = pass_name,
             name_upper = name_upper,
             name_camel = name_camel,
-            module_name = lint_name,
         )
     });
 
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index aaf9ac83d49..281480b8d94 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -9,7 +9,7 @@ keywords = ["clippy", "lint", "plugin"]
 edition = "2021"
 
 [dependencies]
-cargo_metadata = "0.12"
+cargo_metadata = "0.14"
 clippy_utils = { path = "../clippy_utils" }
 if_chain = "1.0"
 itertools = "0.10"
@@ -21,7 +21,7 @@ serde_json = { version = "1.0", optional = true }
 toml = "0.5"
 unicode-normalization = "0.1"
 unicode-script = { version = "0.5", default-features = false }
-semver = "0.11"
+semver = "1.0"
 rustc-semver = "1.1"
 # NOTE: cargo requires serde feat in its url dep
 # see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864>
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 833ad122e0d..4af412ccaf3 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,15 +1,88 @@
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint;
+use clippy_utils::expr_or_init;
 use clippy_utils::ty::is_isize_or_usize;
-use rustc_hir::Expr;
+use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, FloatTy, Ty};
 
 use super::{utils, CAST_POSSIBLE_TRUNCATION};
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
+fn constant_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
+    if let Some((Constant::Int(c), _)) = constant(cx, cx.typeck_results(), expr) {
+        Some(c)
+    } else {
+        None
+    }
+}
+
+fn get_constant_bits(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u64> {
+    constant_int(cx, expr).map(|c| u64::from(128 - c.leading_zeros()))
+}
+
+fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: bool) -> u64 {
+    match expr_or_init(cx, expr).kind {
+        ExprKind::Cast(inner, _) => apply_reductions(cx, nbits, inner, signed),
+        ExprKind::Block(block, _) => block.expr.map_or(nbits, |e| apply_reductions(cx, nbits, e, signed)),
+        ExprKind::Binary(op, left, right) => match op.node {
+            BinOpKind::Div => {
+                apply_reductions(cx, nbits, left, signed)
+                    - (if signed {
+                        0 // let's be conservative here
+                    } else {
+                        // by dividing by 1, we remove 0 bits, etc.
+                        get_constant_bits(cx, right).map_or(0, |b| b.saturating_sub(1))
+                    })
+            },
+            BinOpKind::Rem | BinOpKind::BitAnd => get_constant_bits(cx, right)
+                .unwrap_or(u64::max_value())
+                .min(apply_reductions(cx, nbits, left, signed)),
+            BinOpKind::Shr => {
+                apply_reductions(cx, nbits, left, signed)
+                    - constant_int(cx, right).map_or(0, |s| u64::try_from(s).expect("shift too high"))
+            },
+            _ => nbits,
+        },
+        ExprKind::MethodCall(method, _, [left, right], _) => {
+            if signed {
+                return nbits;
+            }
+            let max_bits = if method.ident.as_str() == "min" {
+                get_constant_bits(cx, right)
+            } else {
+                None
+            };
+            apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::max_value()))
+        },
+        ExprKind::MethodCall(method, _, [_, lo, hi], _) => {
+            if method.ident.as_str() == "clamp" {
+                //FIXME: make this a diagnostic item
+                if let (Some(lo_bits), Some(hi_bits)) = (get_constant_bits(cx, lo), get_constant_bits(cx, hi)) {
+                    return lo_bits.max(hi_bits);
+                }
+            }
+            nbits
+        },
+        ExprKind::MethodCall(method, _, [_value], _) => {
+            if method.ident.name.as_str() == "signum" {
+                0 // do not lint if cast comes from a `signum` function
+            } else {
+                nbits
+            }
+        },
+        _ => nbits,
+    }
+}
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
     let msg = match (cast_from.is_integral(), cast_to.is_integral()) {
         (true, true) => {
-            let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
+            let from_nbits = apply_reductions(
+                cx,
+                utils::int_ty_to_nbits(cast_from, cx.tcx),
+                cast_expr,
+                cast_from.is_signed(),
+            );
             let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
 
             let (should_lint, suffix) = match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) {
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index f0800c6a6f1..233abd17894 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -427,7 +427,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
             fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to);
             fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
             if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
-                cast_possible_truncation::check(cx, expr, cast_from, cast_to);
+                cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
                 cast_possible_wrap::check(cx, expr, cast_from, cast_to);
                 cast_precision_loss::check(cx, expr, cast_from, cast_to);
                 cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to);
diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
index c604516742c..9d8524ec91c 100644
--- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
@@ -1,3 +1,6 @@
+// NOTE: if you add a deprecated lint in this file, please add a corresponding test in
+// tests/ui/deprecated.rs
+
 /// This struct fakes the `Lint` declaration that is usually created by `declare_lint!`. This
 /// enables the simple extraction of the metadata without changing the current deprecation
 /// declaration.
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 7825e5f6ed5..ce59311c4aa 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
                                 target_mut,
                             },
                         ));
-                    }
+                    },
                     _ => (),
                 }
             },
diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs
index 5511c3ea9b6..87ad5178ff0 100644
--- a/src/tools/clippy/clippy_lints/src/doc.rs
+++ b/src/tools/clippy/clippy_lints/src/doc.rs
@@ -1,6 +1,6 @@
 use clippy_utils::attrs::is_doc_hidden;
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_note};
-use clippy_utils::source::first_line_of_span;
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg};
+use clippy_utils::source::{first_line_of_span, snippet_with_applicability};
 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;
@@ -10,7 +10,7 @@ use rustc_ast::token::CommentKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::emitter::EmitterWriter;
-use rustc_errors::Handler;
+use rustc_errors::{Applicability, Handler};
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{AnonConst, Expr, ExprKind, QPath};
@@ -48,7 +48,7 @@ declare_clippy_lint! {
     /// content are not linted.
     ///
     /// In addition, when writing documentation comments, including `[]` brackets
-    /// inside a link text would trip the parser. Therfore, documenting link with
+    /// inside a link text would trip the parser. Therefore, documenting link with
     /// `[`SmallVec<[T; INLINE_CAPACITY]>`]` and then [`SmallVec<[T; INLINE_CAPACITY]>`]: SmallVec
     /// would fail.
     ///
@@ -578,9 +578,12 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                     // text "http://example.com" by pulldown-cmark
                     continue;
                 }
-                headers.safety |= in_heading && text.trim() == "Safety";
-                headers.errors |= in_heading && text.trim() == "Errors";
-                headers.panics |= in_heading && text.trim() == "Panics";
+                let trimmed_text = text.trim();
+                headers.safety |= in_heading && trimmed_text == "Safety";
+                headers.safety |= in_heading && trimmed_text == "Implementation safety";
+                headers.safety |= in_heading && trimmed_text == "Implementation Safety";
+                headers.errors |= in_heading && trimmed_text == "Errors";
+                headers.panics |= in_heading && trimmed_text == "Panics";
                 if in_code {
                     if is_rust {
                         let edition = edition.unwrap_or_else(|| cx.tcx.sess.edition());
@@ -686,10 +689,18 @@ fn check_text(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str
     for word in text.split(|c: char| c.is_whitespace() || c == '\'') {
         // Trim punctuation as in `some comment (see foo::bar).`
         //                                                   ^^
-        // Or even as in `_foo bar_` which is emphasized.
-        let word = word.trim_matches(|c: char| !c.is_alphanumeric());
+        // Or even as in `_foo bar_` which is emphasized. Also preserve `::` as a prefix/suffix.
+        let mut word = word.trim_matches(|c: char| !c.is_alphanumeric() && c != ':');
 
-        if valid_idents.contains(word) {
+        // Remove leading or trailing single `:` which may be part of a sentence.
+        if word.starts_with(':') && !word.starts_with("::") {
+            word = word.trim_start_matches(':');
+        }
+        if word.ends_with(':') && !word.ends_with("::") {
+            word = word.trim_end_matches(':');
+        }
+
+        if valid_idents.contains(word) || word.chars().all(|c| c == ':') {
             continue;
         }
 
@@ -744,17 +755,22 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span) {
         }
     }
 
-    // We assume that mixed-case words are not meant to be put inside bacticks. (Issue #2343)
+    // We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343)
     if has_underscore(word) && has_hyphen(word) {
         return;
     }
 
     if has_underscore(word) || word.contains("::") || is_camel_case(word) {
-        span_lint(
+        let mut applicability = Applicability::MachineApplicable;
+
+        span_lint_and_sugg(
             cx,
             DOC_MARKDOWN,
             span,
-            &format!("you should put `{}` between ticks in the documentation", word),
+            "item in documentation is missing backticks",
+            "try",
+            format!("`{}`", snippet_with_applicability(cx, span, "..", &mut applicability)),
+            applicability,
         );
     }
 }
@@ -793,9 +809,9 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> {
 
         // check for `unwrap`
         if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
-            let reciever_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
-            if is_type_diagnostic_item(self.cx, reciever_ty, sym::Option)
-                || is_type_diagnostic_item(self.cx, reciever_ty, sym::Result)
+            let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
+            if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option)
+                || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result)
             {
                 self.panic_span = Some(expr.span);
             }
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index ac6824672f6..57fd24bd4f0 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -245,11 +245,14 @@ fn try_parse_contains(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Option<(Map
         ExprKind::MethodCall(
             _,
             _,
-            [map, Expr {
-                kind: ExprKind::AddrOf(_, _, key),
-                span: key_span,
-                ..
-            }],
+            [
+                map,
+                Expr {
+                    kind: ExprKind::AddrOf(_, _, key),
+                    span: key_span,
+                    ..
+                },
+            ],
             _,
         ) if key_span.ctxt() == expr.span.ctxt() => {
             let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs
index 174260fabd2..404b67c8f29 100644
--- a/src/tools/clippy/clippy_lints/src/enum_variants.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs
@@ -1,8 +1,8 @@
 //! lint on enum variants that are prefixed or suffixed by the same characters
 
-use clippy_utils::camel_case;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::source::is_present_in_source;
+use clippy_utils::str_utils::{self, count_match_end, count_match_start};
 use rustc_hir::{EnumDef, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -117,26 +117,6 @@ impl_lint_pass!(EnumVariantNames => [
     MODULE_INCEPTION
 ]);
 
-/// Returns the number of chars that match from the start
-#[must_use]
-fn partial_match(pre: &str, name: &str) -> usize {
-    let mut name_iter = name.chars();
-    let _ = name_iter.next_back(); // make sure the name is never fully matched
-    pre.chars().zip(name_iter).take_while(|&(l, r)| l == r).count()
-}
-
-/// Returns the number of chars that match from the end
-#[must_use]
-fn partial_rmatch(post: &str, name: &str) -> usize {
-    let mut name_iter = name.chars();
-    let _ = name_iter.next(); // make sure the name is never fully matched
-    post.chars()
-        .rev()
-        .zip(name_iter.rev())
-        .take_while(|&(l, r)| l == r)
-        .count()
-}
-
 fn check_variant(
     cx: &LateContext<'_>,
     threshold: u64,
@@ -150,7 +130,7 @@ fn check_variant(
     }
     for var in def.variants {
         let name = var.ident.name.as_str();
-        if partial_match(item_name, &name) == item_name_chars
+        if count_match_start(item_name, &name).char_count == item_name_chars
             && name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase())
             && name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric())
         {
@@ -161,7 +141,7 @@ fn check_variant(
                 "variant name starts with the enum's name",
             );
         }
-        if partial_rmatch(item_name, &name) == item_name_chars {
+        if count_match_end(item_name, &name).char_count == item_name_chars {
             span_lint(
                 cx,
                 ENUM_VARIANT_NAMES,
@@ -171,14 +151,14 @@ fn check_variant(
         }
     }
     let first = &def.variants[0].ident.name.as_str();
-    let mut pre = &first[..camel_case::until(&*first)];
-    let mut post = &first[camel_case::from(&*first)..];
+    let mut pre = &first[..str_utils::camel_case_until(&*first).byte_index];
+    let mut post = &first[str_utils::camel_case_start(&*first).byte_index..];
     for var in def.variants {
         let name = var.ident.name.as_str();
 
-        let pre_match = partial_match(pre, &name);
+        let pre_match = count_match_start(pre, &name).byte_count;
         pre = &pre[..pre_match];
-        let pre_camel = camel_case::until(pre);
+        let pre_camel = str_utils::camel_case_until(pre).byte_index;
         pre = &pre[..pre_camel];
         while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() {
             if next.is_numeric() {
@@ -186,18 +166,18 @@ fn check_variant(
             }
             if next.is_lowercase() {
                 let last = pre.len() - last.len_utf8();
-                let last_camel = camel_case::until(&pre[..last]);
-                pre = &pre[..last_camel];
+                let last_camel = str_utils::camel_case_until(&pre[..last]);
+                pre = &pre[..last_camel.byte_index];
             } else {
                 break;
             }
         }
 
-        let post_match = partial_rmatch(post, &name);
-        let post_end = post.len() - post_match;
+        let post_match = count_match_end(post, &name);
+        let post_end = post.len() - post_match.byte_count;
         post = &post[post_end..];
-        let post_camel = camel_case::from(post);
-        post = &post[post_camel..];
+        let post_camel = str_utils::camel_case_start(post);
+        post = &post[post_camel.byte_index..];
     }
     let (what, value) = match (pre.is_empty(), post.is_empty()) {
         (true, true) => return,
@@ -266,14 +246,16 @@ impl LateLintPass<'_> for EnumVariantNames {
                             );
                         }
                     }
-                    if item.vis.node.is_pub() {
-                        let matching = partial_match(mod_camel, &item_camel);
-                        let rmatching = partial_rmatch(mod_camel, &item_camel);
+                    // The `module_name_repetitions` lint should only trigger if the item has the module in its
+                    // name. Having the same name is accepted.
+                    if item.vis.node.is_pub() && item_camel.len() > mod_camel.len() {
+                        let matching = count_match_start(mod_camel, &item_camel);
+                        let rmatching = count_match_end(mod_camel, &item_camel);
                         let nchars = mod_camel.chars().count();
 
                         let is_word_beginning = |c: char| c == '_' || c.is_uppercase() || c.is_numeric();
 
-                        if matching == nchars {
+                        if matching.char_count == nchars {
                             match item_camel.chars().nth(nchars) {
                                 Some(c) if is_word_beginning(c) => span_lint(
                                     cx,
@@ -284,7 +266,7 @@ impl LateLintPass<'_> for EnumVariantNames {
                                 _ => (),
                             }
                         }
-                        if rmatching == nchars {
+                        if rmatching.char_count == nchars {
                             span_lint(
                                 cx,
                                 MODULE_NAME_REPETITIONS,
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 765a6c7585a..9247343b52a 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -169,13 +169,16 @@ fn check_inputs(cx: &LateContext<'_>, params: &[Param<'_>], call_args: &[Expr<'_
         }
         match *cx.typeck_results().expr_adjustments(arg) {
             [] => true,
-            [Adjustment {
-                kind: Adjust::Deref(None),
-                ..
-            }, Adjustment {
-                kind: Adjust::Borrow(AutoBorrow::Ref(_, mu2)),
-                ..
-            }] => {
+            [
+                Adjustment {
+                    kind: Adjust::Deref(None),
+                    ..
+                },
+                Adjustment {
+                    kind: Adjust::Borrow(AutoBorrow::Ref(_, mu2)),
+                    ..
+                },
+            ] => {
                 // re-borrow with the same mutability is allowed
                 let ty = cx.typeck_results().expr_ty(arg);
                 matches!(*ty.kind(), ty::Ref(.., mu1) if mu1 == mu2.into())
diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs
index c22f9d0e170..7169ac9ad6c 100644
--- a/src/tools/clippy/clippy_lints/src/format.rs
+++ b/src/tools/clippy/clippy_lints/src/format.rs
@@ -49,15 +49,19 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
 
         let mut applicability = Applicability::MachineApplicable;
         if format_args.value_args.is_empty() {
-            if_chain! {
-                if let [e] = &*format_args.format_string_parts;
-                if let ExprKind::Lit(lit) = &e.kind;
-                if let Some(s_src) = snippet_opt(cx, lit.span);
-                then {
-                    // Simulate macro expansion, converting {{ and }} to { and }.
-                    let s_expand = s_src.replace("{{", "{").replace("}}", "}");
-                    let sugg = format!("{}.to_string()", s_expand);
-                    span_useless_format(cx, call_site, sugg, applicability);
+            if format_args.format_string_parts.is_empty() {
+                span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability);
+            } else {
+                if_chain! {
+                    if let [e] = &*format_args.format_string_parts;
+                    if let ExprKind::Lit(lit) = &e.kind;
+                    if let Some(s_src) = snippet_opt(cx, lit.span);
+                    then {
+                        // Simulate macro expansion, converting {{ and }} to { and }.
+                        let s_expand = s_src.replace("{{", "{").replace("}}", "}");
+                        let sugg = format!("{}.to_string()", s_expand);
+                        span_useless_format(cx, call_site, sugg, applicability);
+                    }
                 }
             }
         } else if let [value] = *format_args.value_args {
@@ -89,6 +93,18 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
     }
 }
 
+fn span_useless_format_empty(cx: &LateContext<'_>, span: Span, sugg: String, applicability: Applicability) {
+    span_lint_and_sugg(
+        cx,
+        USELESS_FORMAT,
+        span,
+        "useless use of `format!`",
+        "consider using `String::new()`",
+        sugg,
+        applicability,
+    );
+}
+
 fn span_useless_format(cx: &LateContext<'_>, span: Span, sugg: String, applicability: Applicability) {
     span_lint_and_sugg(
         cx,
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 3ce91d421ba..ac938156237 100644
--- a/src/tools/clippy/clippy_lints/src/if_not_else.rs
+++ b/src/tools/clippy/clippy_lints/src/if_not_else.rs
@@ -2,9 +2,9 @@
 //! on the condition
 
 use clippy_utils::diagnostics::span_lint_and_help;
-use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp};
-use rustc_lint::{EarlyContext, EarlyLintPass};
-use rustc_middle::lint::in_external_macro;
+use clippy_utils::is_else_clause;
+use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
@@ -46,14 +46,21 @@ declare_clippy_lint! {
 
 declare_lint_pass!(IfNotElse => [IF_NOT_ELSE]);
 
-impl EarlyLintPass for IfNotElse {
-    fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) {
-        if in_external_macro(cx.sess, item.span) {
+impl LateLintPass<'_> for IfNotElse {
+    fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) {
+        // While loops will be desugared to ExprKind::If. This will cause the lint to fire.
+        // To fix this, return early if this span comes from a macro or desugaring.
+        if item.span.from_expansion() {
             return;
         }
-        if let ExprKind::If(ref cond, _, Some(ref els)) = item.kind {
+        if let ExprKind::If(cond, _, Some(els)) = item.kind {
             if let ExprKind::Block(..) = els.kind {
-                match cond.kind {
+                // Disable firing the lint in "else if" expressions.
+                if is_else_clause(cx.tcx, item) {
+                    return;
+                }
+
+                match cond.peel_drop_temps().kind {
                     ExprKind::Unary(UnOp::Not, _) => {
                         span_lint_and_help(
                             cx,
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 49b69dd072a..6850e0c3476 100644
--- a/src/tools/clippy/clippy_lints/src/int_plus_one.rs
+++ b/src/tools/clippy/clippy_lints/src/int_plus_one.rs
@@ -89,7 +89,7 @@ impl IntPlusOne {
                     },
                     _ => None,
                 }
-            }
+            },
             // case where `x + 1 <= ...` or `1 + x <= ...`
             (BinOpKind::Le, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _)
                 if lhskind.node == BinOpKind::Add =>
@@ -104,7 +104,7 @@ impl IntPlusOne {
                     },
                     _ => None,
                 }
-            }
+            },
             // case where `... >= y - 1` or `... >= -1 + y`
             (BinOpKind::Le, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) => {
                 match (rhskind.node, &rhslhs.kind, &rhsrhs.kind) {
diff --git a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
index b1f70b30c12..82438d85c7a 100644
--- a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
@@ -1,5 +1,3 @@
-use std::cmp::Ordering;
-
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf;
@@ -7,11 +5,11 @@ use rustc_middle::ty::{self, IntTy, UintTy};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::Span;
 
+use clippy_utils::comparisons;
 use clippy_utils::comparisons::Rel;
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{constant_full_int, FullInt};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::source::snippet;
-use clippy_utils::{comparisons, sext};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -39,53 +37,6 @@ declare_clippy_lint! {
 
 declare_lint_pass!(InvalidUpcastComparisons => [INVALID_UPCAST_COMPARISONS]);
 
-#[derive(Copy, Clone, Debug, Eq)]
-enum FullInt {
-    S(i128),
-    U(u128),
-}
-
-impl FullInt {
-    #[allow(clippy::cast_sign_loss)]
-    #[must_use]
-    fn cmp_s_u(s: i128, u: u128) -> Ordering {
-        if s < 0 {
-            Ordering::Less
-        } else if u > (i128::MAX as u128) {
-            Ordering::Greater
-        } else {
-            (s as u128).cmp(&u)
-        }
-    }
-}
-
-impl PartialEq for FullInt {
-    #[must_use]
-    fn eq(&self, other: &Self) -> bool {
-        self.partial_cmp(other).expect("`partial_cmp` only returns `Some(_)`") == Ordering::Equal
-    }
-}
-
-impl PartialOrd for FullInt {
-    #[must_use]
-    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        Some(match (self, other) {
-            (&Self::S(s), &Self::S(o)) => s.cmp(&o),
-            (&Self::U(s), &Self::U(o)) => s.cmp(&o),
-            (&Self::S(s), &Self::U(o)) => Self::cmp_s_u(s, o),
-            (&Self::U(s), &Self::S(o)) => Self::cmp_s_u(o, s).reverse(),
-        })
-    }
-}
-
-impl Ord for FullInt {
-    #[must_use]
-    fn cmp(&self, other: &Self) -> Ordering {
-        self.partial_cmp(other)
-            .expect("`partial_cmp` for FullInt can never return `None`")
-    }
-}
-
 fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<(FullInt, FullInt)> {
     if let ExprKind::Cast(cast_exp, _) = expr.kind {
         let pre_cast_ty = cx.typeck_results().expr_ty(cast_exp);
@@ -118,19 +69,6 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) ->
     }
 }
 
-fn node_as_const_fullint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<FullInt> {
-    let val = constant(cx, cx.typeck_results(), expr)?.0;
-    if let Constant::Int(const_int) = val {
-        match *cx.typeck_results().expr_ty(expr).kind() {
-            ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))),
-            ty::Uint(_) => Some(FullInt::U(const_int)),
-            _ => None,
-        }
-    } else {
-        None
-    }
-}
-
 fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, always: bool) {
     if let ExprKind::Cast(cast_val, _) = expr.kind {
         span_lint(
@@ -156,7 +94,7 @@ fn upcast_comparison_bounds_err<'tcx>(
     invert: bool,
 ) {
     if let Some((lb, ub)) = lhs_bounds {
-        if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) {
+        if let Some(norm_rhs_val) = constant_full_int(cx, cx.typeck_results(), rhs) {
             if rel == Rel::Eq || rel == Rel::Ne {
                 if norm_rhs_val < lb || norm_rhs_val > ub {
                     err_upcast_comparison(cx, span, lhs, rel == Rel::Ne);
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_all.rs b/src/tools/clippy/clippy_lints/src/lib.register_all.rs
index c949ee23ecc..15edb79d36c 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_all.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_all.rs
@@ -76,7 +76,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
     LintId::of(get_last_with_len::GET_LAST_WITH_LEN),
     LintId::of(identity_op::IDENTITY_OP),
     LintId::of(if_let_mutex::IF_LET_MUTEX),
-    LintId::of(if_then_panic::IF_THEN_PANIC),
     LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING),
     LintId::of(infinite_iter::INFINITE_ITER),
     LintId::of(inherent_to_string::INHERENT_TO_STRING),
@@ -218,6 +217,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
     LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
     LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
     LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS),
+    LintId::of(non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY),
     LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS),
     LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
     LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
@@ -282,6 +282,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
     LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
     LintId::of(unicode::INVISIBLE_CHARACTERS),
     LintId::of(uninit_vec::UNINIT_VEC),
+    LintId::of(unit_hash::UNIT_HASH),
     LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
     LintId::of(unit_types::UNIT_ARG),
     LintId::of(unit_types::UNIT_CMP),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs
index ff56a6081fb..4217fd3a3ea 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs
@@ -64,6 +64,7 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve
     LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
     LintId::of(unicode::INVISIBLE_CHARACTERS),
     LintId::of(uninit_vec::UNINIT_VEC),
+    LintId::of(unit_hash::UNIT_HASH),
     LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
     LintId::of(unit_types::UNIT_CMP),
     LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs
index e8dd3708c8e..2cb86418e3c 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs
@@ -159,7 +159,6 @@ store.register_lints(&[
     identity_op::IDENTITY_OP,
     if_let_mutex::IF_LET_MUTEX,
     if_not_else::IF_NOT_ELSE,
-    if_then_panic::IF_THEN_PANIC,
     if_then_some_else_none::IF_THEN_SOME_ELSE_NONE,
     implicit_hasher::IMPLICIT_HASHER,
     implicit_return::IMPLICIT_RETURN,
@@ -216,6 +215,7 @@ store.register_lints(&[
     loops::WHILE_LET_ON_ITERATOR,
     macro_use::MACRO_USE_IMPORTS,
     main_recursion::MAIN_RECURSION,
+    manual_assert::MANUAL_ASSERT,
     manual_async_fn::MANUAL_ASYNC_FN,
     manual_map::MANUAL_MAP,
     manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE,
@@ -327,6 +327,7 @@ store.register_lints(&[
     misc_early::DUPLICATE_UNDERSCORE_ARGUMENT,
     misc_early::MIXED_CASE_HEX_LITERALS,
     misc_early::REDUNDANT_PATTERN,
+    misc_early::SEPARATED_LITERAL_SUFFIX,
     misc_early::UNNEEDED_FIELD_PATTERN,
     misc_early::UNNEEDED_WILDCARD_PATTERN,
     misc_early::UNSEPARATED_LITERAL_SUFFIX,
@@ -431,6 +432,7 @@ store.register_lints(&[
     strings::STRING_ADD_ASSIGN,
     strings::STRING_FROM_UTF8_AS_BYTES,
     strings::STRING_LIT_AS_BYTES,
+    strings::STRING_SLICE,
     strings::STRING_TO_STRING,
     strings::STR_TO_STRING,
     strlen_on_c_strings::STRLEN_ON_C_STRINGS,
@@ -476,6 +478,7 @@ store.register_lints(&[
     unicode::NON_ASCII_LITERAL,
     unicode::UNICODE_NOT_NFC,
     uninit_vec::UNINIT_VEC,
+    unit_hash::UNIT_HASH,
     unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD,
     unit_types::LET_UNIT_VALUE,
     unit_types::UNIT_ARG,
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs
index 1e54482a8da..44c75a11eec 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs
@@ -17,7 +17,6 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
     LintId::of(missing_const_for_fn::MISSING_CONST_FOR_FN),
     LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
     LintId::of(mutex_atomic::MUTEX_INTEGER),
-    LintId::of(non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY),
     LintId::of(nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES),
     LintId::of(option_if_let_else::OPTION_IF_LET_ELSE),
     LintId::of(path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs b/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs
index 268349d2848..404ca20b5ab 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs
@@ -48,6 +48,7 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
     LintId::of(loops::EXPLICIT_INTO_ITER_LOOP),
     LintId::of(loops::EXPLICIT_ITER_LOOP),
     LintId::of(macro_use::MACRO_USE_IMPORTS),
+    LintId::of(manual_assert::MANUAL_ASSERT),
     LintId::of(manual_ok_or::MANUAL_OK_OR),
     LintId::of(match_on_vec_items::MATCH_ON_VEC_ITEMS),
     LintId::of(matches::MATCH_BOOL),
@@ -65,7 +66,6 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
     LintId::of(methods::MAP_UNWRAP_OR),
     LintId::of(misc::FLOAT_CMP),
     LintId::of(misc::USED_UNDERSCORE_BINDING),
-    LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX),
     LintId::of(mut_mut::MUT_MUT),
     LintId::of(needless_bitwise_bool::NEEDLESS_BITWISE_BOOL),
     LintId::of(needless_borrow::REF_BINDING_TO_REFERENCE),
@@ -88,7 +88,6 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
     LintId::of(transmute::TRANSMUTE_PTR_TO_PTR),
     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),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs
index 3d68a6e9009..eab389a9bd8 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs
@@ -35,7 +35,9 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve
     LintId::of(methods::GET_UNWRAP),
     LintId::of(methods::UNWRAP_USED),
     LintId::of(misc::FLOAT_CMP_CONST),
+    LintId::of(misc_early::SEPARATED_LITERAL_SUFFIX),
     LintId::of(misc_early::UNNEEDED_FIELD_PATTERN),
+    LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX),
     LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),
     LintId::of(missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES),
     LintId::of(missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS),
@@ -53,11 +55,13 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve
     LintId::of(shadow::SHADOW_SAME),
     LintId::of(shadow::SHADOW_UNRELATED),
     LintId::of(strings::STRING_ADD),
+    LintId::of(strings::STRING_SLICE),
     LintId::of(strings::STRING_TO_STRING),
     LintId::of(strings::STR_TO_STRING),
     LintId::of(types::RC_BUFFER),
     LintId::of(types::RC_MUTEX),
     LintId::of(undocumented_unsafe_blocks::UNDOCUMENTED_UNSAFE_BLOCKS),
+    LintId::of(unicode::NON_ASCII_LITERAL),
     LintId::of(unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS),
     LintId::of(unwrap_in_result::UNWRAP_IN_RESULT),
     LintId::of(verbose_file_reads::VERBOSE_FILE_READS),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_style.rs b/src/tools/clippy/clippy_lints/src/lib.register_style.rs
index a39c111c574..744880bda3e 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_style.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_style.rs
@@ -27,7 +27,6 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
     LintId::of(functions::DOUBLE_MUST_USE),
     LintId::of(functions::MUST_USE_UNIT),
     LintId::of(functions::RESULT_UNIT_ERR),
-    LintId::of(if_then_panic::IF_THEN_PANIC),
     LintId::of(inherent_to_string::INHERENT_TO_STRING),
     LintId::of(len_zero::COMPARISON_TO_EMPTY),
     LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs b/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs
index 8859787fbc8..a3f964d1580 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs
@@ -15,6 +15,7 @@ store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec!
     LintId::of(loops::MUT_RANGE_BOUND),
     LintId::of(methods::SUSPICIOUS_MAP),
     LintId::of(mut_key::MUTABLE_KEY_TYPE),
+    LintId::of(non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY),
     LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
     LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
 ])
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index ed7e8277023..7174d0a082e 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -228,7 +228,6 @@ mod get_last_with_len;
 mod identity_op;
 mod if_let_mutex;
 mod if_not_else;
-mod if_then_panic;
 mod if_then_some_else_none;
 mod implicit_hasher;
 mod implicit_return;
@@ -255,6 +254,7 @@ mod literal_representation;
 mod loops;
 mod macro_use;
 mod main_recursion;
+mod manual_assert;
 mod manual_async_fn;
 mod manual_map;
 mod manual_non_exhaustive;
@@ -364,6 +364,7 @@ mod undocumented_unsafe_blocks;
 mod undropped_manually_drops;
 mod unicode;
 mod uninit_vec;
+mod unit_hash;
 mod unit_return_expecting_ord;
 mod unit_types;
 mod unnamed_address;
@@ -522,6 +523,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| Box::new(collapsible_match::CollapsibleMatch));
     store.register_late_pass(|| Box::new(unicode::Unicode));
     store.register_late_pass(|| Box::new(uninit_vec::UninitVec));
+    store.register_late_pass(|| Box::new(unit_hash::UnitHash));
     store.register_late_pass(|| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd));
     store.register_late_pass(|| Box::new(strings::StringAdd));
     store.register_late_pass(|| Box::new(implicit_return::ImplicitReturn));
@@ -666,7 +668,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(|| Box::new(double_parens::DoubleParens));
     store.register_late_pass(|| Box::new(to_string_in_display::ToStringInDisplay::new()));
     store.register_early_pass(|| Box::new(unsafe_removed_from_name::UnsafeNameRemoval));
-    store.register_early_pass(|| Box::new(if_not_else::IfNotElse));
     store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse));
     store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne));
     store.register_early_pass(|| Box::new(formatting::Formatting));
@@ -720,6 +721,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| Box::new(option_if_let_else::OptionIfLetElse));
     store.register_late_pass(|| Box::new(future_not_send::FutureNotSend));
     store.register_late_pass(|| Box::new(if_let_mutex::IfLetMutex));
+    store.register_late_pass(|| Box::new(if_not_else::IfNotElse));
     store.register_late_pass(|| Box::new(equatable_if_let::PatternEquality));
     store.register_late_pass(|| Box::new(mut_mutex_lock::MutMutexLock));
     store.register_late_pass(|| Box::new(match_on_vec_items::MatchOnVecItems));
@@ -770,14 +772,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(move || Box::new(self_named_constructors::SelfNamedConstructors));
     store.register_late_pass(move || Box::new(feature_name::FeatureName));
     store.register_late_pass(move || Box::new(iter_not_returning_iterator::IterNotReturningIterator));
-    store.register_late_pass(move || Box::new(if_then_panic::IfThenPanic));
+    store.register_late_pass(move || Box::new(manual_assert::ManualAssert));
     let enable_raw_pointer_heuristic_for_send = conf.enable_raw_pointer_heuristic_for_send;
     store.register_late_pass(move || Box::new(non_send_fields_in_send_ty::NonSendFieldInSendTy::new(enable_raw_pointer_heuristic_for_send)));
     store.register_late_pass(move || Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::default()));
     store.register_late_pass(|| Box::new(match_str_case_mismatch::MatchStrCaseMismatch));
     store.register_late_pass(move || Box::new(format_args::FormatArgs));
     store.register_late_pass(|| Box::new(trailing_empty_array::TrailingEmptyArray));
-
+    // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
 #[rustfmt::skip]
@@ -828,6 +830,7 @@ fn register_removed_non_tool_lints(store: &mut rustc_lint::LintStore) {
 ///
 /// Used in `./src/driver.rs`.
 pub fn register_renamed(ls: &mut rustc_lint::LintStore) {
+    // NOTE: when renaming a lint, add a corresponding test to tests/ui/rename.rs
     ls.register_renamed("clippy::stutter", "clippy::module_name_repetitions");
     ls.register_renamed("clippy::new_without_default_derive", "clippy::new_without_default");
     ls.register_renamed("clippy::cyclomatic_complexity", "clippy::cognitive_complexity");
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index e5e6f8d25cc..cb0b96e0652 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -378,11 +378,15 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
 
     fn visit_ty(&mut self, ty: &'tcx Ty<'_>) {
         match ty.kind {
-            TyKind::OpaqueDef(item, _) => {
+            TyKind::OpaqueDef(item, bounds) => {
                 let map = self.cx.tcx.hir();
                 let item = map.item(item);
                 walk_item(self, item);
                 walk_ty(self, ty);
+                self.lts.extend(bounds.iter().filter_map(|bound| match bound {
+                    GenericArg::Lifetime(l) => Some(RefLt::Named(l.name.ident().name)),
+                    _ => None,
+                }));
             },
             TyKind::BareFn(&BareFnTy { decl, .. }) => {
                 let mut sub_visitor = RefVisitor::new(self.cx);
diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs
index 2f7360210ba..f9f515cc40a 100644
--- a/src/tools/clippy/clippy_lints/src/loops/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs
@@ -338,7 +338,7 @@ pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic
                     sugg::Sugg::hir_with_applicability(cx, arg_inner, "_", applic_ref).maybe_par(),
                     meth_name,
                 )
-            }
+            },
             _ => format!(
                 "{}.into_iter()",
                 sugg::Sugg::hir_with_applicability(cx, arg, "_", applic_ref).maybe_par()
diff --git a/src/tools/clippy/clippy_lints/src/if_then_panic.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs
index e8cea5529e8..e55aa3f1850 100644
--- a/src/tools/clippy/clippy_lints/src/if_then_panic.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_assert.rs
@@ -26,14 +26,14 @@ declare_clippy_lint! {
     /// let sad_people: Vec<&str> = vec![];
     /// assert!(sad_people.is_empty(), "there are sad people: {:?}", sad_people);
     /// ```
-    pub IF_THEN_PANIC,
-    style,
+    pub MANUAL_ASSERT,
+    pedantic,
     "`panic!` and only a `panic!` in `if`-then statement"
 }
 
-declare_lint_pass!(IfThenPanic => [IF_THEN_PANIC]);
+declare_lint_pass!(ManualAssert => [MANUAL_ASSERT]);
 
-impl LateLintPass<'_> for IfThenPanic {
+impl LateLintPass<'_> for ManualAssert {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         if_chain! {
             if let Expr {
@@ -54,23 +54,24 @@ impl LateLintPass<'_> for IfThenPanic {
             if !cx.tcx.sess.source_map().is_multiline(cond.span);
 
             then {
-                let span = if let Some(panic_expn) = PanicExpn::parse(semi) {
+                let call = if_chain! {
+                    if let ExprKind::Block(block, _) = semi.kind;
+                    if let Some(init) = block.expr;
+                    then {
+                        init
+                    } else {
+                        semi
+                    }
+                };
+                let span = if let Some(panic_expn) = PanicExpn::parse(call) {
                     match *panic_expn.format_args.value_args {
                         [] => panic_expn.format_args.format_string_span,
                         [.., last] => panic_expn.format_args.format_string_span.to(last.span),
                     }
+                } else if let ExprKind::Call(_, [format_args]) = call.kind {
+                    format_args.span
                 } else {
-                    if_chain! {
-                        if let ExprKind::Block(block, _) = semi.kind;
-                        if let Some(init) = block.expr;
-                        if let ExprKind::Call(_, [format_args]) = init.kind;
-
-                        then {
-                            format_args.span
-                        } else {
-                            return
-                        }
-                    }
+                    return
                 };
                 let mut applicability = Applicability::MachineApplicable;
                 let sugg = snippet_with_applicability(cx, span, "..", &mut applicability);
@@ -86,7 +87,7 @@ impl LateLintPass<'_> for IfThenPanic {
 
                 span_lint_and_sugg(
                     cx,
-                    IF_THEN_PANIC,
+                    MANUAL_ASSERT,
                     expr.span,
                     "only a `panic!` in `if`-then statement",
                     "try",
diff --git a/src/tools/clippy/clippy_lints/src/match_str_case_mismatch.rs b/src/tools/clippy/clippy_lints/src/match_str_case_mismatch.rs
index a83f38e3d51..f501593c518 100644
--- a/src/tools/clippy/clippy_lints/src/match_str_case_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/match_str_case_mismatch.rs
@@ -127,10 +127,10 @@ fn get_case_method(segment_ident_str: &str) -> Option<CaseMethod> {
 
 fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(Span, SymbolStr)> {
     let case_check = match case_method {
-        CaseMethod::LowerCase => |input: &str| -> bool { input.chars().all(char::is_lowercase) },
-        CaseMethod::AsciiLowerCase => |input: &str| -> bool { input.chars().all(|c| matches!(c, 'a'..='z')) },
-        CaseMethod::UpperCase => |input: &str| -> bool { input.chars().all(char::is_uppercase) },
-        CaseMethod::AsciiUppercase => |input: &str| -> bool { input.chars().all(|c| matches!(c, 'A'..='Z')) },
+        CaseMethod::LowerCase => |input: &str| -> bool { input.chars().all(|c| c.to_lowercase().next() == Some(c)) },
+        CaseMethod::AsciiLowerCase => |input: &str| -> bool { !input.chars().any(|c| c.is_ascii_uppercase()) },
+        CaseMethod::UpperCase => |input: &str| -> bool { input.chars().all(|c| c.to_uppercase().next() == Some(c)) },
+        CaseMethod::AsciiUppercase => |input: &str| -> bool { !input.chars().any(|c| c.is_ascii_lowercase()) },
     };
 
     for arm in arms {
@@ -153,7 +153,7 @@ fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(
 
 fn lint(cx: &LateContext<'_>, case_method: &CaseMethod, bad_case_span: Span, bad_case_str: &str) {
     let (method_str, suggestion) = match case_method {
-        CaseMethod::LowerCase => ("to_lower_case", bad_case_str.to_lowercase()),
+        CaseMethod::LowerCase => ("to_lowercase", bad_case_str.to_lowercase()),
         CaseMethod::AsciiLowerCase => ("to_ascii_lowercase", bad_case_str.to_ascii_lowercase()),
         CaseMethod::UpperCase => ("to_uppercase", bad_case_str.to_uppercase()),
         CaseMethod::AsciiUppercase => ("to_ascii_uppercase", bad_case_str.to_ascii_uppercase()),
diff --git a/src/tools/clippy/clippy_lints/src/matches.rs b/src/tools/clippy/clippy_lints/src/matches.rs
index b643fba5d32..eb311983b29 100644
--- a/src/tools/clippy/clippy_lints/src/matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, miri_to_const, Constant};
+use clippy_utils::consts::{constant, constant_full_int, miri_to_const, FullInt};
 use clippy_utils::diagnostics::{
     multispan_sugg, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
 };
@@ -930,9 +930,8 @@ fn check_match_bool(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
 fn check_overlapping_arms<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) {
     if arms.len() >= 2 && cx.typeck_results().expr_ty(ex).is_integral() {
         let ranges = all_ranges(cx, arms, cx.typeck_results().expr_ty(ex));
-        let type_ranges = type_ranges(&ranges);
-        if !type_ranges.is_empty() {
-            if let Some((start, end)) = overlapping(&type_ranges) {
+        if !ranges.is_empty() {
+            if let Some((start, end)) = overlapping(&ranges) {
                 span_lint_and_note(
                     cx,
                     MATCH_OVERLAPPING_ARM,
@@ -968,8 +967,7 @@ fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm
                     }
                     if_chain! {
                         if matching_wild;
-                        if let ExprKind::Block(block, _) = arm.body.kind;
-                        if is_panic_block(block);
+                        if is_panic_call(arm.body);
                         then {
                             // `Err(_)` or `Err(_e)` arm with `panic!` found
                             span_lint_and_note(cx,
@@ -1172,14 +1170,19 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
 }
 
 // If the block contains only a `panic!` macro (as expression or statement)
-fn is_panic_block(block: &Block<'_>) -> bool {
-    match (&block.expr, block.stmts.len(), block.stmts.first()) {
-        (&Some(exp), 0, _) => is_expn_of(exp.span, "panic").is_some() && is_expn_of(exp.span, "unreachable").is_none(),
-        (&None, 1, Some(stmt)) => {
-            is_expn_of(stmt.span, "panic").is_some() && is_expn_of(stmt.span, "unreachable").is_none()
-        },
-        _ => false,
-    }
+fn is_panic_call(expr: &Expr<'_>) -> bool {
+    // Unwrap any wrapping blocks
+    let span = if let ExprKind::Block(block, _) = expr.kind {
+        match (&block.expr, block.stmts.len(), block.stmts.first()) {
+            (&Some(exp), 0, _) => exp.span,
+            (&None, 1, Some(stmt)) => stmt.span,
+            _ => return false,
+        }
+    } else {
+        expr.span
+    };
+
+    is_expn_of(span, "panic").is_some() && is_expn_of(span, "unreachable").is_none()
 }
 
 fn check_match_ref_pats<'a, 'b, I>(cx: &LateContext<'_>, ex: &Expr<'_>, pats: I, expr: &Expr<'_>)
@@ -1601,7 +1604,7 @@ fn opt_parent_let<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option<&'a Local<'
 }
 
 /// Gets all arms that are unbounded `PatRange`s.
-fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) -> Vec<SpannedRange<Constant>> {
+fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) -> Vec<SpannedRange<FullInt>> {
     arms.iter()
         .filter_map(|arm| {
             if let Arm { pat, guard: None, .. } = *arm {
@@ -1614,21 +1617,25 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                         Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
                         None => miri_to_const(ty.numeric_max_val(cx.tcx)?)?,
                     };
-                    let rhs = match range_end {
-                        RangeEnd::Included => Bound::Included(rhs),
-                        RangeEnd::Excluded => Bound::Excluded(rhs),
+
+                    let lhs_val = lhs.int_value(cx, ty)?;
+                    let rhs_val = rhs.int_value(cx, ty)?;
+
+                    let rhs_bound = match range_end {
+                        RangeEnd::Included => Bound::Included(rhs_val),
+                        RangeEnd::Excluded => Bound::Excluded(rhs_val),
                     };
                     return Some(SpannedRange {
                         span: pat.span,
-                        node: (lhs, rhs),
+                        node: (lhs_val, rhs_bound),
                     });
                 }
 
                 if let PatKind::Lit(value) = pat.kind {
-                    let value = constant(cx, cx.typeck_results(), value)?.0;
+                    let value = constant_full_int(cx, cx.typeck_results(), value)?;
                     return Some(SpannedRange {
                         span: pat.span,
-                        node: (value.clone(), Bound::Included(value)),
+                        node: (value, Bound::Included(value)),
                     });
                 }
             }
@@ -1643,32 +1650,6 @@ pub struct SpannedRange<T> {
     pub node: (T, Bound<T>),
 }
 
-type TypedRanges = Vec<SpannedRange<u128>>;
-
-/// Gets all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway
-/// and other types than
-/// `Uint` and `Int` probably don't make sense.
-fn type_ranges(ranges: &[SpannedRange<Constant>]) -> TypedRanges {
-    ranges
-        .iter()
-        .filter_map(|range| match range.node {
-            (Constant::Int(start), Bound::Included(Constant::Int(end))) => Some(SpannedRange {
-                span: range.span,
-                node: (start, Bound::Included(end)),
-            }),
-            (Constant::Int(start), Bound::Excluded(Constant::Int(end))) => Some(SpannedRange {
-                span: range.span,
-                node: (start, Bound::Excluded(end)),
-            }),
-            (Constant::Int(start), Bound::Unbounded) => Some(SpannedRange {
-                span: range.span,
-                node: (start, Bound::Unbounded),
-            }),
-            _ => None,
-        })
-        .collect()
-}
-
 // Checks if arm has the form `None => None`
 fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
     matches!(arm.pat.kind, PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone))
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 1a32af5dc7a..b4dacb2580c 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
@@ -85,7 +85,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol,
                     if expr.hir_id == self_arg.hir_id && ty != cx.typeck_results().expr_ty_adjusted(expr) =>
                 {
                     return;
-                }
+                },
                 ExprKind::MethodCall(_, _, [self_arg, ..], _) if expr.hir_id == self_arg.hir_id => true,
                 ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
                 | ExprKind::Field(..)
@@ -100,7 +100,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol,
                 ) =>
             {
                 return;
-            }
+            },
             _ => false,
         };
 
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 b5bbbb09092..fe9ffde0d33 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
@@ -186,7 +186,7 @@ pub(super) fn check<'tcx>(
                         check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None);
                     }
                 }
-            }
+            },
             _ => (),
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs b/src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs
index 6f65778e119..06ba968fa4e 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs
@@ -1,4 +1,3 @@
-use super::MiscEarlyLints;
 use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast::{Expr, ExprKind, UnOp};
 use rustc_lint::EarlyContext;
@@ -6,18 +5,14 @@ use rustc_lint::EarlyContext;
 use super::DOUBLE_NEG;
 
 pub(super) fn check(cx: &EarlyContext<'_>, expr: &Expr) {
-    match expr.kind {
-        ExprKind::Unary(UnOp::Neg, ref inner) => {
-            if let ExprKind::Unary(UnOp::Neg, _) = inner.kind {
-                span_lint(
-                    cx,
-                    DOUBLE_NEG,
-                    expr.span,
-                    "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op",
-                );
-            }
-        },
-        ExprKind::Lit(ref lit) => MiscEarlyLints::check_lit(cx, lit),
-        _ => (),
+    if let ExprKind::Unary(UnOp::Neg, ref inner) = expr.kind {
+        if let ExprKind::Unary(UnOp::Neg, _) = inner.kind {
+            span_lint(
+                cx,
+                DOUBLE_NEG,
+                expr.span,
+                "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op",
+            );
+        }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs b/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs
new file mode 100644
index 00000000000..1165c19a0cf
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs
@@ -0,0 +1,38 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use rustc_ast::ast::Lit;
+use rustc_errors::Applicability;
+use rustc_lint::EarlyContext;
+
+use super::{SEPARATED_LITERAL_SUFFIX, UNSEPARATED_LITERAL_SUFFIX};
+
+pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &str, sugg_type: &str) {
+    let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) {
+        val
+    } else {
+        return; // It's useless so shouldn't lint.
+    };
+    // Do not lint when literal is unsuffixed.
+    if !suffix.is_empty() {
+        if lit_snip.as_bytes()[maybe_last_sep_idx] == b'_' {
+            span_lint_and_sugg(
+                cx,
+                SEPARATED_LITERAL_SUFFIX,
+                lit.span,
+                &format!("{} type suffix should not be separated by an underscore", sugg_type),
+                "remove the underscore",
+                format!("{}{}", &lit_snip[..maybe_last_sep_idx], suffix),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            span_lint_and_sugg(
+                cx,
+                UNSEPARATED_LITERAL_SUFFIX,
+                lit.span,
+                &format!("{} type suffix should be separated by an underscore", sugg_type),
+                "add an underscore",
+                format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix),
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
index b32feab4ee3..7c3f5f22ade 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
@@ -1,15 +1,15 @@
 mod builtin_type_shadow;
 mod double_neg;
+mod literal_suffix;
 mod mixed_case_hex_literals;
 mod redundant_pattern;
 mod unneeded_field_pattern;
 mod unneeded_wildcard_pattern;
-mod unseparated_literal_suffix;
 mod zero_prefixed_literal;
 
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::source::snippet_opt;
-use rustc_ast::ast::{Expr, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
+use rustc_ast::ast::{Expr, ExprKind, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
 use rustc_ast::visit::FnKind;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_lint::{EarlyContext, EarlyLintPass};
@@ -115,9 +115,11 @@ declare_clippy_lint! {
     /// ### What it does
     /// Warns if literal suffixes are not separated by an
     /// underscore.
+    /// To enforce unseparated literal suffix style,
+    /// see the `separated_literal_suffix` lint.
     ///
     /// ### Why is this bad?
-    /// It is much less readable.
+    /// Suffix style should be consistent.
     ///
     /// ### Example
     /// ```rust
@@ -128,12 +130,34 @@ declare_clippy_lint! {
     /// let y = 123832_i32;
     /// ```
     pub UNSEPARATED_LITERAL_SUFFIX,
-    pedantic,
+    restriction,
     "literals whose suffix is not separated by an underscore"
 }
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Warns if literal suffixes are separated by an underscore.
+    /// To enforce separated literal suffix style,
+    /// see the `unseparated_literal_suffix` lint.
+    ///
+    /// ### Why is this bad?
+    /// Suffix style should be consistent.
+    ///
+    /// ### Example
+    /// ```rust
+    /// // Bad
+    /// let y = 123832_i32;
+    ///
+    /// // Good
+    /// let y = 123832i32;
+    /// ```
+    pub SEPARATED_LITERAL_SUFFIX,
+    restriction,
+    "literals whose suffix is separated by an underscore"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
     /// Warns if an integral constant literal starts with `0`.
     ///
     /// ### Why is this bad?
@@ -260,6 +284,7 @@ declare_lint_pass!(MiscEarlyLints => [
     DOUBLE_NEG,
     MIXED_CASE_HEX_LITERALS,
     UNSEPARATED_LITERAL_SUFFIX,
+    SEPARATED_LITERAL_SUFFIX,
     ZERO_PREFIXED_LITERAL,
     BUILTIN_TYPE_SHADOW,
     REDUNDANT_PATTERN,
@@ -310,6 +335,10 @@ impl EarlyLintPass for MiscEarlyLints {
         if in_external_macro(cx.sess, expr.span) {
             return;
         }
+
+        if let ExprKind::Lit(ref lit) = expr.kind {
+            MiscEarlyLints::check_lit(cx, lit);
+        }
         double_neg::check(cx, expr);
     }
 }
@@ -332,7 +361,7 @@ impl MiscEarlyLints {
                 LitIntType::Unsigned(ty) => ty.name_str(),
                 LitIntType::Unsuffixed => "",
             };
-            unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "integer");
+            literal_suffix::check(cx, lit, &lit_snip, suffix, "integer");
             if lit_snip.starts_with("0x") {
                 mixed_case_hex_literals::check(cx, lit, suffix, &lit_snip);
             } else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") {
@@ -342,7 +371,7 @@ impl MiscEarlyLints {
             }
         } else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind {
             let suffix = float_ty.name_str();
-            unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "float");
+            literal_suffix::check(cx, lit, &lit_snip, suffix, "float");
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/unseparated_literal_suffix.rs b/src/tools/clippy/clippy_lints/src/misc_early/unseparated_literal_suffix.rs
deleted file mode 100644
index 2018aa6184a..00000000000
--- a/src/tools/clippy/clippy_lints/src/misc_early/unseparated_literal_suffix.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use rustc_ast::ast::Lit;
-use rustc_errors::Applicability;
-use rustc_lint::EarlyContext;
-
-use super::UNSEPARATED_LITERAL_SUFFIX;
-
-pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &str, sugg_type: &str) {
-    let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) {
-        val
-    } else {
-        return; // It's useless so shouldn't lint.
-    };
-    // Do not lint when literal is unsuffixed.
-    if !suffix.is_empty() && lit_snip.as_bytes()[maybe_last_sep_idx] != b'_' {
-        span_lint_and_sugg(
-            cx,
-            UNSEPARATED_LITERAL_SUFFIX,
-            lit.span,
-            &format!("{} type suffix should be separated by an underscore", sugg_type),
-            "add an underscore",
-            format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix),
-            Applicability::MachineApplicable,
-        );
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs
index f351d0098b7..d41b5474564 100644
--- a/src/tools/clippy/clippy_lints/src/module_style.rs
+++ b/src/tools/clippy/clippy_lints/src/module_style.rs
@@ -106,7 +106,7 @@ impl EarlyLintPass for ModStyle {
                     }
                     process_paths_for_mod_files(path, &mut folder_segments, &mut mod_folders);
                     check_self_named_mod_exists(cx, path, file);
-                }
+                },
                 _ => {},
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrow.rs b/src/tools/clippy/clippy_lints/src/needless_borrow.rs
index 1b2495d764d..f1be90c44f9 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrow.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrow.rs
@@ -107,14 +107,18 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow {
         if let ExprKind::AddrOf(BorrowKind::Ref, mutability, inner) = e.kind {
             if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(inner).kind() {
                 for adj3 in cx.typeck_results().expr_adjustments(e).windows(3) {
-                    if let [Adjustment {
-                        kind: Adjust::Deref(_), ..
-                    }, Adjustment {
-                        kind: Adjust::Deref(_), ..
-                    }, Adjustment {
-                        kind: Adjust::Borrow(_),
-                        ..
-                    }] = *adj3
+                    if let [
+                        Adjustment {
+                            kind: Adjust::Deref(_), ..
+                        },
+                        Adjustment {
+                            kind: Adjust::Deref(_), ..
+                        },
+                        Adjustment {
+                            kind: Adjust::Borrow(_),
+                            ..
+                        },
+                    ] = *adj3
                     {
                         let help_msg_ty = if matches!(mutability, Mutability::Not) {
                             format!("&{}", ty)
diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
index 374b7bd5964..7ebf84d400f 100644
--- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
+++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
@@ -44,7 +44,7 @@ declare_clippy_lint! {
     /// Use thread-safe types like [`std::sync::Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html)
     /// or specify correct bounds on generic type parameters (`T: Send`).
     pub NON_SEND_FIELDS_IN_SEND_TY,
-    nursery,
+    suspicious,
     "there is field that does not implement `Send` in a `Send` struct"
 }
 
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 a62eb069989..cbe1c5d44d5 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
@@ -22,7 +22,7 @@ declare_clippy_lint! {
     /// expression).
     ///
     /// ### Why is this bad?
-    /// Using the dedicated functions of the Option type is clearer and
+    /// Using the dedicated functions of the `Option` type is clearer and
     /// more concise than an `if let` expression.
     ///
     /// ### Known problems
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 92a4801a846..8a36e20fc97 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -3,16 +3,16 @@
 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::ty::walk_ptrs_hir_ty;
 use clippy_utils::{expr_path_res, is_lint_allowed, match_any_diagnostic_items, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
+use rustc_hir::def::Res;
 use rustc_hir::{
-    BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, Impl, ImplItem, ImplItemKind, Item,
-    ItemKind, Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind,
+    BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, Impl, ImplItem, ImplItemKind, Item, ItemKind,
+    Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::Symbol;
@@ -153,7 +153,7 @@ declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_PTR_USA
 impl<'tcx> LateLintPass<'tcx> for Ptr {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
         if let ItemKind::Fn(ref sig, _, body_id) = item.kind {
-            check_fn(cx, sig.decl, item.hir_id(), Some(body_id));
+            check_fn(cx, sig.decl, Some(body_id));
         }
     }
 
@@ -165,7 +165,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
                     return; // ignore trait impls
                 }
             }
-            check_fn(cx, sig.decl, item.hir_id(), Some(body_id));
+            check_fn(cx, sig.decl, Some(body_id));
         }
     }
 
@@ -176,7 +176,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
             } else {
                 None
             };
-            check_fn(cx, sig.decl, item.hir_id(), body_id);
+            check_fn(cx, sig.decl, body_id);
         }
     }
 
@@ -244,13 +244,10 @@ fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 }
 
 #[allow(clippy::too_many_lines)]
-fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: Option<BodyId>) {
-    let fn_def_id = cx.tcx.hir().local_def_id(fn_id);
-    let sig = cx.tcx.fn_sig(fn_def_id);
-    let fn_ty = sig.skip_binder();
+fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, opt_body_id: Option<BodyId>) {
     let body = opt_body_id.map(|id| cx.tcx.hir().body(id));
 
-    for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() {
+    for (idx, arg) in decl.inputs.iter().enumerate() {
         // Honor the allow attribute on parameters. See issue 5644.
         if let Some(body) = &body {
             if is_lint_allowed(cx, PTR_ARG, body.params[idx].hir_id) {
@@ -258,8 +255,20 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
             }
         }
 
-        if let ty::Ref(_, ty, Mutability::Not) = ty.kind() {
-            if is_type_diagnostic_item(cx, ty, sym::Vec) {
+        let (item_name, path) = if_chain! {
+            if let TyKind::Rptr(_, MutTy { ty, mutbl: Mutability::Not }) = arg.kind;
+            if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind;
+            if let Res::Def(_, did) = path.res;
+            if let Some(item_name) = cx.tcx.get_diagnostic_name(did);
+            then {
+                (item_name, path)
+            } else {
+                continue
+            }
+        };
+
+        match item_name {
+            sym::Vec => {
                 if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) {
                     span_lint_and_then(
                         cx,
@@ -289,7 +298,8 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
                         },
                     );
                 }
-            } else if is_type_diagnostic_item(cx, ty, sym::String) {
+            },
+            sym::String => {
                 if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_string()"), ("as_str", "")]) {
                     span_lint_and_then(
                         cx,
@@ -311,7 +321,8 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
                         },
                     );
                 }
-            } else if is_type_diagnostic_item(cx, ty, sym::PathBuf) {
+            },
+            sym::PathBuf => {
                 if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_path_buf()"), ("as_path", "")]) {
                     span_lint_and_then(
                         cx,
@@ -338,11 +349,10 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
                         },
                     );
                 }
-            } else if match_type(cx, ty, &paths::COW) {
+            },
+            sym::Cow => {
                 if_chain! {
-                    if let TyKind::Rptr(_, MutTy { ty, ..} ) = arg.kind;
-                    if let TyKind::Path(QPath::Resolved(None, pp)) = ty.kind;
-                    if let [ref bx] = *pp.segments;
+                    if let [ref bx] = *path.segments;
                     if let Some(params) = bx.args;
                     if !params.parenthesized;
                     if let Some(inner) = params.args.iter().find_map(|arg| match arg {
@@ -363,7 +373,8 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
                         );
                     }
                 }
-            }
+            },
+            _ => {},
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index 4d616e26bfc..f63ef163bcb 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -172,23 +172,17 @@ impl QuestionMark {
         }
     }
 
-    fn expression_returns_unmodified_err(
-        cx: &LateContext<'_>,
-        expression: &Expr<'_>,
-        origin_hir_id: &Expr<'_>,
-    ) -> bool {
-        match expression.kind {
+    fn expression_returns_unmodified_err(cx: &LateContext<'_>, expr: &Expr<'_>, cond_expr: &Expr<'_>) -> bool {
+        match expr.kind {
             ExprKind::Block(block, _) => {
                 if let Some(return_expression) = Self::return_expression(block) {
-                    return Self::expression_returns_unmodified_err(cx, return_expression, origin_hir_id);
+                    return Self::expression_returns_unmodified_err(cx, return_expression, cond_expr);
                 }
 
                 false
             },
-            ExprKind::Ret(Some(expr)) | ExprKind::Call(expr, _) => {
-                Self::expression_returns_unmodified_err(cx, expr, origin_hir_id)
-            },
-            ExprKind::Path(_) => path_to_local(expression) == path_to_local(origin_hir_id),
+            ExprKind::Ret(Some(ret_expr)) => Self::expression_returns_unmodified_err(cx, ret_expr, cond_expr),
+            ExprKind::Path(_) => path_to_local(expr) == path_to_local(cond_expr),
             _ => false,
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index 35b6bde5696..6435107b8b4 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -107,51 +107,87 @@ declare_clippy_lint! {
     "calling `as_bytes` on a string literal instead of using a byte string literal"
 }
 
-declare_lint_pass!(StringAdd => [STRING_ADD, STRING_ADD_ASSIGN]);
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for slice operations on strings
+    ///
+    /// ### Why is this bad?
+    /// UTF-8 characters span multiple bytes, and it is easy to inadvertently confuse character
+    /// counts and string indices. This may lead to panics, and should warrant some test cases
+    /// containing wide UTF-8 characters. This lint is most useful in code that should avoid
+    /// panics at all costs.
+    ///
+    /// ### Known problems
+    /// Probably lots of false positives. If an index comes from a known valid position (e.g.
+    /// obtained via `char_indices` over the same string), it is totally OK.
+    ///
+    /// # Example
+    /// ```rust,should_panic
+    /// &"Ölkanne"[1..];
+    /// ```
+    pub STRING_SLICE,
+    restriction,
+    "slicing a string"
+}
+
+declare_lint_pass!(StringAdd => [STRING_ADD, STRING_ADD_ASSIGN, STRING_SLICE]);
 
 impl<'tcx> LateLintPass<'tcx> for StringAdd {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         if in_external_macro(cx.sess(), e.span) {
             return;
         }
-
-        if let ExprKind::Binary(
-            Spanned {
-                node: BinOpKind::Add, ..
-            },
-            left,
-            _,
-        ) = e.kind
-        {
-            if is_string(cx, left) {
-                if !is_lint_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) {
-                    let parent = get_parent_expr(cx, e);
-                    if let Some(p) = parent {
-                        if let ExprKind::Assign(target, _, _) = p.kind {
-                            // avoid duplicate matches
-                            if SpanlessEq::new(cx).eq_expr(target, left) {
-                                return;
+        match e.kind {
+            ExprKind::Binary(
+                Spanned {
+                    node: BinOpKind::Add, ..
+                },
+                left,
+                _,
+            ) => {
+                if is_string(cx, left) {
+                    if !is_lint_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) {
+                        let parent = get_parent_expr(cx, e);
+                        if let Some(p) = parent {
+                            if let ExprKind::Assign(target, _, _) = p.kind {
+                                // avoid duplicate matches
+                                if SpanlessEq::new(cx).eq_expr(target, left) {
+                                    return;
+                                }
                             }
                         }
                     }
+                    span_lint(
+                        cx,
+                        STRING_ADD,
+                        e.span,
+                        "you added something to a string. Consider using `String::push_str()` instead",
+                    );
                 }
-                span_lint(
-                    cx,
-                    STRING_ADD,
-                    e.span,
-                    "you added something to a string. Consider using `String::push_str()` instead",
-                );
-            }
-        } else if let ExprKind::Assign(target, src, _) = e.kind {
-            if is_string(cx, target) && is_add(cx, src, target) {
-                span_lint(
-                    cx,
-                    STRING_ADD_ASSIGN,
-                    e.span,
-                    "you assigned the result of adding something to this string. Consider using \
-                     `String::push_str()` instead",
-                );
-            }
+            },
+            ExprKind::Assign(target, src, _) => {
+                if is_string(cx, target) && is_add(cx, src, target) {
+                    span_lint(
+                        cx,
+                        STRING_ADD_ASSIGN,
+                        e.span,
+                        "you assigned the result of adding something to this string. Consider using \
+                         `String::push_str()` instead",
+                    );
+                }
+            },
+            ExprKind::Index(target, _idx) => {
+                let e_ty = cx.typeck_results().expr_ty(target).peel_refs();
+                if matches!(e_ty.kind(), ty::Str) || is_type_diagnostic_item(cx, e_ty, sym::String) {
+                    span_lint(
+                        cx,
+                        STRING_SLICE,
+                        e.span,
+                        "indexing into a string may panic if the index is within a UTF-8 character",
+                    );
+                }
+            },
+            _ => {},
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index e08e4d03c7e..11aef50991b 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -145,8 +145,9 @@ impl UndocumentedUnsafeBlocks {
         let file_name = source_map.span_to_filename(between_span);
         let source_file = source_map.get_source_file(&file_name)?;
 
-        let lex_start = (between_span.lo().0 + 1) as usize;
-        let src_str = source_file.src.as_ref()?[lex_start..between_span.hi().0 as usize].to_string();
+        let lex_start = (between_span.lo().0 - source_file.start_pos.0 + 1) as usize;
+        let lex_end = (between_span.hi().0 - source_file.start_pos.0) as usize;
+        let src_str = source_file.src.as_ref()?[lex_start..lex_end].to_string();
 
         let mut pos = 0;
         let mut comment = false;
diff --git a/src/tools/clippy/clippy_lints/src/unicode.rs b/src/tools/clippy/clippy_lints/src/unicode.rs
index f337dec8f2b..f49ce696a04 100644
--- a/src/tools/clippy/clippy_lints/src/unicode.rs
+++ b/src/tools/clippy/clippy_lints/src/unicode.rs
@@ -45,7 +45,7 @@ declare_clippy_lint! {
     /// let x = String::from("\u{20ac}");
     /// ```
     pub NON_ASCII_LITERAL,
-    pedantic,
+    restriction,
     "using any literal non-ASCII chars in a string literal instead of using the `\\u` escape"
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/unit_hash.rs b/src/tools/clippy/clippy_lints/src/unit_hash.rs
new file mode 100644
index 00000000000..a3a3f2d41c7
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/unit_hash.rs
@@ -0,0 +1,77 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Detects `().hash(_)`.
+    ///
+    /// ### Why is this bad?
+    /// Hashing a unit value doesn't do anything as the implementation of `Hash` for `()` is a no-op.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # use std::hash::Hash;
+    /// # use std::collections::hash_map::DefaultHasher;
+    /// # enum Foo { Empty, WithValue(u8) }
+    /// # use Foo::*;
+    /// # let mut state = DefaultHasher::new();
+    /// # let my_enum = Foo::Empty;
+    /// match my_enum {
+    /// 	Empty => ().hash(&mut state),
+    /// 	WithValue(x) => x.hash(&mut state),
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # use std::hash::Hash;
+    /// # use std::collections::hash_map::DefaultHasher;
+    /// # enum Foo { Empty, WithValue(u8) }
+    /// # use Foo::*;
+    /// # let mut state = DefaultHasher::new();
+    /// # let my_enum = Foo::Empty;
+    /// match my_enum {
+    /// 	Empty => 0_u8.hash(&mut state),
+    /// 	WithValue(x) => x.hash(&mut state),
+    /// }
+    /// ```
+    pub UNIT_HASH,
+    correctness,
+    "hashing a unit value, which does nothing"
+}
+declare_lint_pass!(UnitHash => [UNIT_HASH]);
+
+impl LateLintPass<'tcx> for UnitHash {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if_chain! {
+            if let ExprKind::MethodCall(name_ident, _, args, _) = &expr.kind;
+            if name_ident.ident.name == sym::hash;
+            if let [recv, state_param] = args;
+            if cx.typeck_results().expr_ty(recv).is_unit();
+            then {
+                span_lint_and_then(
+                    cx,
+                    UNIT_HASH,
+                    expr.span,
+                    "this call to `hash` on the unit type will do nothing",
+                    |diag| {
+                        diag.span_suggestion(
+                            expr.span,
+                            "remove the call to `hash` or consider using",
+                            format!(
+                                "0_u8.hash({})",
+                                snippet(cx, state_param.span, ".."),
+                            ),
+                            Applicability::MaybeIncorrect,
+                        );
+                        diag.note("the implementation of `Hash` for `()` is a no-op");
+                    }
+                );
+            }
+        }
+    }
+}
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 a4680ae137b..6447e3fa2ca 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
@@ -13,7 +13,7 @@ use rustc_span::{sym, Span};
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for functions of type Result that contain `expect()` or `unwrap()`
+    /// Checks for functions of type `Result` that contain `expect()` or `unwrap()`
     ///
     /// ### Why is this bad?
     /// These functions promote recoverable errors to non-recoverable errors which may be undesirable in code bases which wish to avoid panics.
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index d05c52122d5..122a5ce3fc8 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -288,10 +288,10 @@ define_Conf! {
     ///
     /// The list of imports to always rename, a fully qualified path followed by the rename.
     (enforced_import_renames: Vec<crate::utils::conf::Rename> = Vec::new()),
-    /// Lint: RESTRICTED_SCRIPTS.
+    /// Lint: DISALLOWED_SCRIPT_IDENTS.
     ///
     /// The list of unicode scripts allowed to be used in the scope.
-    (allowed_scripts: Vec<String> = vec!["Latin".to_string()]),
+    (allowed_scripts: Vec<String> = ["Latin"].iter().map(ToString::to_string).collect()),
     /// Lint: NON_SEND_FIELDS_IN_SEND_TY.
     ///
     /// Whether to apply the raw pointer heuristic to determine if a type is `Send`.
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 0d27874b7af..99cf4c1ed40 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -512,12 +512,21 @@ fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
     let mut lines = attrs.iter().filter_map(ast::Attribute::doc_str);
     let mut docs = String::from(&*lines.next()?.as_str());
     let mut in_code_block = false;
+    let mut is_code_block_rust = false;
     for line in lines {
-        docs.push('\n');
         let line = line.as_str();
         let line = &*line;
+
+        // Rustdoc hides code lines starting with `# ` and this removes them from Clippy's lint list :)
+        if is_code_block_rust && line.trim_start().starts_with("# ") {
+            continue;
+        }
+
+        // The line should be represented in the lint list, even if it's just an empty line
+        docs.push('\n');
         if let Some(info) = line.trim_start().strip_prefix("```") {
             in_code_block = !in_code_block;
+            is_code_block_rust = false;
             if in_code_block {
                 let lang = info
                     .trim()
@@ -528,6 +537,8 @@ fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
                     .unwrap_or("rust");
                 docs.push_str("```");
                 docs.push_str(lang);
+
+                is_code_block_rust = lang == "rust";
                 continue;
             }
         }
diff --git a/src/tools/clippy/clippy_utils/src/camel_case.rs b/src/tools/clippy/clippy_utils/src/camel_case.rs
deleted file mode 100644
index a6636e39137..00000000000
--- a/src/tools/clippy/clippy_utils/src/camel_case.rs
+++ /dev/null
@@ -1,117 +0,0 @@
-/// Returns the index of the character after the first camel-case component of `s`.
-#[must_use]
-pub fn until(s: &str) -> usize {
-    let mut iter = s.char_indices();
-    if let Some((_, first)) = iter.next() {
-        if !first.is_uppercase() {
-            return 0;
-        }
-    } else {
-        return 0;
-    }
-    let mut up = true;
-    let mut last_i = 0;
-    for (i, c) in iter {
-        if up {
-            if c.is_lowercase() {
-                up = false;
-            } else {
-                return last_i;
-            }
-        } else if c.is_uppercase() {
-            up = true;
-            last_i = i;
-        } else if !c.is_lowercase() {
-            return i;
-        }
-    }
-    if up { last_i } else { s.len() }
-}
-
-/// Returns index of the last camel-case component of `s`.
-#[must_use]
-pub fn from(s: &str) -> usize {
-    let mut iter = s.char_indices().rev();
-    if let Some((_, first)) = iter.next() {
-        if !first.is_lowercase() {
-            return s.len();
-        }
-    } else {
-        return s.len();
-    }
-    let mut down = true;
-    let mut last_i = s.len();
-    for (i, c) in iter {
-        if down {
-            if c.is_uppercase() {
-                down = false;
-                last_i = i;
-            } else if !c.is_lowercase() {
-                return last_i;
-            }
-        } else if c.is_lowercase() {
-            down = true;
-        } else if c.is_uppercase() {
-            last_i = i;
-        } else {
-            return last_i;
-        }
-    }
-    last_i
-}
-
-#[cfg(test)]
-mod test {
-    use super::{from, until};
-
-    #[test]
-    fn from_full() {
-        assert_eq!(from("AbcDef"), 0);
-        assert_eq!(from("Abc"), 0);
-        assert_eq!(from("ABcd"), 0);
-        assert_eq!(from("ABcdEf"), 0);
-        assert_eq!(from("AabABcd"), 0);
-    }
-
-    #[test]
-    fn from_partial() {
-        assert_eq!(from("abcDef"), 3);
-        assert_eq!(from("aDbc"), 1);
-        assert_eq!(from("aabABcd"), 3);
-    }
-
-    #[test]
-    fn from_not() {
-        assert_eq!(from("AbcDef_"), 7);
-        assert_eq!(from("AbcDD"), 5);
-    }
-
-    #[test]
-    fn from_caps() {
-        assert_eq!(from("ABCD"), 4);
-    }
-
-    #[test]
-    fn until_full() {
-        assert_eq!(until("AbcDef"), 6);
-        assert_eq!(until("Abc"), 3);
-    }
-
-    #[test]
-    fn until_not() {
-        assert_eq!(until("abcDef"), 0);
-        assert_eq!(until("aDbc"), 0);
-    }
-
-    #[test]
-    fn until_partial() {
-        assert_eq!(until("AbcDef_"), 6);
-        assert_eq!(until("CallTypeC"), 8);
-        assert_eq!(until("AbcDD"), 3);
-    }
-
-    #[test]
-    fn until_caps() {
-        assert_eq!(until("ABCD"), 0);
-    }
-}
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 8bf31807d55..04347672e0f 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -155,6 +155,19 @@ impl Constant {
             _ => None,
         }
     }
+
+    /// Returns the integer value or `None` if `self` or `val_type` is not integer type.
+    pub fn int_value(&self, cx: &LateContext<'_>, val_type: Ty<'_>) -> Option<FullInt> {
+        if let Constant::Int(const_int) = *self {
+            match *val_type.kind() {
+                ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))),
+                ty::Uint(_) => Some(FullInt::U(const_int)),
+                _ => None,
+            }
+        } else {
+            None
+        }
+    }
 }
 
 /// Parses a `LitKind` to a `Constant`.
@@ -202,6 +215,52 @@ pub fn constant_simple<'tcx>(
     constant(lcx, typeck_results, e).and_then(|(cst, res)| if res { None } else { Some(cst) })
 }
 
+pub fn constant_full_int(
+    lcx: &LateContext<'tcx>,
+    typeck_results: &ty::TypeckResults<'tcx>,
+    e: &Expr<'_>,
+) -> Option<FullInt> {
+    constant_simple(lcx, typeck_results, e)?.int_value(lcx, typeck_results.expr_ty(e))
+}
+
+#[derive(Copy, Clone, Debug, Eq)]
+pub enum FullInt {
+    S(i128),
+    U(u128),
+}
+
+impl PartialEq for FullInt {
+    #[must_use]
+    fn eq(&self, other: &Self) -> bool {
+        self.cmp(other) == Ordering::Equal
+    }
+}
+
+impl PartialOrd for FullInt {
+    #[must_use]
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for FullInt {
+    #[must_use]
+    fn cmp(&self, other: &Self) -> Ordering {
+        use FullInt::{S, U};
+
+        fn cmp_s_u(s: i128, u: u128) -> Ordering {
+            u128::try_from(s).map_or(Ordering::Less, |x| x.cmp(&u))
+        }
+
+        match (*self, *other) {
+            (S(s), S(o)) => s.cmp(&o),
+            (U(s), U(o)) => s.cmp(&o),
+            (S(s), U(o)) => cmp_s_u(s, o),
+            (U(s), S(o)) => cmp_s_u(o, s).reverse(),
+        }
+    }
+}
+
 /// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckResults`.
 pub fn constant_context<'a, 'tcx>(
     lcx: &'a LateContext<'tcx>,
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index 9302e5c21fa..d47b002ad7a 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -72,7 +72,7 @@ pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<Mult
 /// 6  |     let other_f64_nan = 0.0f64 / 0.0;
 ///    |                         ^^^^^^^^^^^^
 ///    |
-///    = help: Consider using `f64::NAN` if you would like a constant representing NaN
+///    = help: consider using `f64::NAN` if you would like a constant representing NaN
 /// ```
 pub fn span_lint_and_help<'a, T: LintContext>(
     cx: &'a T,
diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs
index 60c4cb361aa..b3a9a1de2ec 100644
--- a/src/tools/clippy/clippy_utils/src/higher.rs
+++ b/src/tools/clippy/clippy_utils/src/higher.rs
@@ -1,14 +1,14 @@
-//! This module contains functions that retrieves specifiec elements.
+//! This module contains functions that retrieve specific elements.
 
 #![deny(clippy::missing_docs_in_private_items)]
 
 use crate::ty::is_type_diagnostic_item;
-use crate::{is_expn_of, last_path_segment, match_def_path, paths};
+use crate::{is_expn_of, last_path_segment, match_def_path, path_to_local_id, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::{self, LitKind};
 use rustc_hir as hir;
 use rustc_hir::{
-    Arm, Block, BorrowKind, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath, StmtKind, UnOp,
+    Arm, Block, BorrowKind, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, PatKind, QPath, StmtKind, UnOp,
 };
 use rustc_lint::LateContext;
 use rustc_span::{sym, symbol, ExpnKind, Span, Symbol};
@@ -513,6 +513,8 @@ pub struct FormatArgsExpn<'tcx> {
     pub format_string_parts: &'tcx [Expr<'tcx>],
     /// Symbols corresponding to [`Self::format_string_parts`]
     pub format_string_symbols: Vec<Symbol>,
+    /// Match arm patterns, the `arg0`, etc. from the next field `args`
+    pub arg_names: &'tcx [Pat<'tcx>],
     /// Expressions like `ArgumentV1::new(arg0, Debug::fmt)`
     pub args: &'tcx [Expr<'tcx>],
     /// The final argument passed to `Arguments::new_v1_formatted`, if applicable
@@ -557,6 +559,7 @@ impl FormatArgsExpn<'tcx> {
                     _ => None,
                 })
                 .collect();
+            if let PatKind::Tuple(arg_names, None) = arm.pat.kind;
             if let ExprKind::Array(args) = arm.body.kind;
             then {
                 Some(FormatArgsExpn {
@@ -564,6 +567,7 @@ impl FormatArgsExpn<'tcx> {
                     value_args,
                     format_string_parts,
                     format_string_symbols,
+                    arg_names,
                     args,
                     fmt_expr,
                 })
@@ -587,9 +591,15 @@ impl FormatArgsExpn<'tcx> {
                             if let Some(position_field) = fields.iter().find(|f| f.ident.name == sym::position);
                             if let ExprKind::Lit(lit) = &position_field.expr.kind;
                             if let LitKind::Int(position, _) = lit.node;
+                            if let Ok(i) = usize::try_from(position);
+                            let arg = &self.args[i];
+                            if let ExprKind::Call(_, [arg_name, _]) = arg.kind;
+                            if let Some(j) = self
+                                .arg_names
+                                .iter()
+                                .position(|pat| path_to_local_id(arg_name, pat.hir_id));
                             then {
-                                let i = usize::try_from(position).unwrap();
-                                Some(FormatArgsArg { value: self.value_args[i], arg: &self.args[i], fmt: Some(fmt) })
+                                Some(FormatArgsArg { value: self.value_args[j], arg, fmt: Some(fmt) })
                             } else {
                                 None
                             }
@@ -718,9 +728,7 @@ impl PanicExpn<'tcx> {
     /// Parses an expanded `panic!` invocation
     pub fn parse(expr: &'tcx Expr<'tcx>) -> Option<Self> {
         if_chain! {
-            if let ExprKind::Block(block, _) = expr.kind;
-            if let Some(init) = block.expr;
-            if let ExprKind::Call(_, [format_args]) = init.kind;
+            if let ExprKind::Call(_, [format_args]) = expr.kind;
             let expn_data = expr.span.ctxt().outer_expn_data();
             if let Some(format_args) = FormatArgsExpn::parse(format_args);
             then {
@@ -770,13 +778,13 @@ pub fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -
                     }
                     return Some(VecInitKind::WithExprCapacity(arg.hir_id));
                 }
-            }
+            },
             ExprKind::Path(QPath::Resolved(_, path))
                 if match_def_path(cx, path.res.opt_def_id()?, &paths::DEFAULT_TRAIT_METHOD)
                     && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec) =>
             {
                 return Some(VecInitKind::Default);
-            }
+            },
             _ => (),
         }
     }
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 9bc380ca6ca..086fbc9d3dd 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -37,7 +37,6 @@ pub mod sym_helper;
 #[allow(clippy::module_name_repetitions)]
 pub mod ast_utils;
 pub mod attrs;
-pub mod camel_case;
 pub mod comparisons;
 pub mod consts;
 pub mod diagnostics;
@@ -50,6 +49,7 @@ pub mod paths;
 pub mod ptr;
 pub mod qualify_min_const_fn;
 pub mod source;
+pub mod str_utils;
 pub mod sugg;
 pub mod ty;
 pub mod usage;
@@ -712,7 +712,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
 /// Checks if the top level expression can be moved into a closure as is.
 /// Currently checks for:
 /// * Break/Continue outside the given loop HIR ids.
-/// * Yield/Return statments.
+/// * Yield/Return statements.
 /// * Inline assembly.
 /// * Usages of a field of a local where the type of the local can be partially moved.
 ///
@@ -844,10 +844,13 @@ pub fn capture_local_usage(cx: &LateContext<'tcx>, e: &Expr<'_>) -> CaptureKind
     let mut capture_expr_ty = e;
 
     for (parent_id, parent) in cx.tcx.hir().parent_iter(e.hir_id) {
-        if let [Adjustment {
-            kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
-            target,
-        }, ref adjust @ ..] = *cx
+        if let [
+            Adjustment {
+                kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
+                target,
+            },
+            ref adjust @ ..,
+        ] = *cx
             .typeck_results()
             .adjustments()
             .get(child_id)
@@ -1232,9 +1235,7 @@ pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Opti
     for (_, node) in tcx.hir().parent_iter(expr.hir_id) {
         match node {
             Node::Expr(
-                e
-                @
-                Expr {
+                e @ Expr {
                     kind: ExprKind::Loop(..) | ExprKind::Closure(..),
                     ..
                 },
@@ -1692,10 +1693,12 @@ pub fn is_async_fn(kind: FnKind<'_>) -> bool {
 pub fn get_async_fn_body(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
     if let ExprKind::Call(
         _,
-        &[Expr {
-            kind: ExprKind::Closure(_, _, body, _, _),
-            ..
-        }],
+        &[
+            Expr {
+                kind: ExprKind::Closure(_, _, body, _, _),
+                ..
+            },
+        ],
     ) = body.value.kind
     {
         if let ExprKind::Block(
@@ -2123,7 +2126,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
     vis.found
 }
 
-/// Checks whether item either has `test` attribute appelied, or
+/// Checks whether item either has `test` attribute applied, or
 /// is a module with `test` in its name.
 ///
 /// Note: If you use this function, please add a `#[test]` case in `tests/ui_test`.
diff --git a/src/tools/clippy/clippy_utils/src/str_utils.rs b/src/tools/clippy/clippy_utils/src/str_utils.rs
new file mode 100644
index 00000000000..cba96e05a24
--- /dev/null
+++ b/src/tools/clippy/clippy_utils/src/str_utils.rs
@@ -0,0 +1,230 @@
+/// Dealing with sting indices can be hard, this struct ensures that both the
+/// character and byte index are provided for correct indexing.
+#[derive(Debug, Default, PartialEq, Eq)]
+pub struct StrIndex {
+    pub char_index: usize,
+    pub byte_index: usize,
+}
+
+impl StrIndex {
+    pub fn new(char_index: usize, byte_index: usize) -> Self {
+        Self { char_index, byte_index }
+    }
+}
+
+/// Returns the index of the character after the first camel-case component of `s`.
+///
+/// ```
+/// assert_eq!(camel_case_until("AbcDef"), StrIndex::new(6, 6));
+/// assert_eq!(camel_case_until("ABCD"), StrIndex::new(0, 0));
+/// assert_eq!(camel_case_until("AbcDD"), StrIndex::new(3, 3));
+/// assert_eq!(camel_case_until("Abc\u{f6}\u{f6}DD"), StrIndex::new(5, 7));
+/// ```
+#[must_use]
+pub fn camel_case_until(s: &str) -> StrIndex {
+    let mut iter = s.char_indices().enumerate();
+    if let Some((_char_index, (_, first))) = iter.next() {
+        if !first.is_uppercase() {
+            return StrIndex::new(0, 0);
+        }
+    } else {
+        return StrIndex::new(0, 0);
+    }
+    let mut up = true;
+    let mut last_index = StrIndex::new(0, 0);
+    for (char_index, (byte_index, c)) in iter {
+        if up {
+            if c.is_lowercase() {
+                up = false;
+            } else {
+                return last_index;
+            }
+        } else if c.is_uppercase() {
+            up = true;
+            last_index.byte_index = byte_index;
+            last_index.char_index = char_index;
+        } else if !c.is_lowercase() {
+            return StrIndex::new(char_index, byte_index);
+        }
+    }
+
+    if up {
+        last_index
+    } else {
+        StrIndex::new(s.chars().count(), s.len())
+    }
+}
+
+/// Returns index of the last camel-case component of `s`.
+///
+/// ```
+/// assert_eq!(camel_case_start("AbcDef"), StrIndex::new(0, 0));
+/// assert_eq!(camel_case_start("abcDef"), StrIndex::new(3, 3));
+/// assert_eq!(camel_case_start("ABCD"), StrIndex::new(4, 4));
+/// assert_eq!(camel_case_start("abcd"), StrIndex::new(4, 4));
+/// assert_eq!(camel_case_start("\u{f6}\u{f6}cd"), StrIndex::new(4, 6));
+/// ```
+#[must_use]
+pub fn camel_case_start(s: &str) -> StrIndex {
+    let char_count = s.chars().count();
+    let range = 0..char_count;
+    let mut iter = range.rev().zip(s.char_indices().rev());
+    if let Some((char_index, (_, first))) = iter.next() {
+        if !first.is_lowercase() {
+            return StrIndex::new(char_index, s.len());
+        }
+    } else {
+        return StrIndex::new(char_count, s.len());
+    }
+    let mut down = true;
+    let mut last_index = StrIndex::new(char_count, s.len());
+    for (char_index, (byte_index, c)) in iter {
+        if down {
+            if c.is_uppercase() {
+                down = false;
+                last_index.byte_index = byte_index;
+                last_index.char_index = char_index;
+            } else if !c.is_lowercase() {
+                return last_index;
+            }
+        } else if c.is_lowercase() {
+            down = true;
+        } else if c.is_uppercase() {
+            last_index.byte_index = byte_index;
+            last_index.char_index = char_index;
+        } else {
+            return last_index;
+        }
+    }
+    last_index
+}
+
+/// Dealing with sting comparison can be complicated, this struct ensures that both the
+/// character and byte count are provided for correct indexing.
+#[derive(Debug, Default, PartialEq, Eq)]
+pub struct StrCount {
+    pub char_count: usize,
+    pub byte_count: usize,
+}
+
+impl StrCount {
+    pub fn new(char_count: usize, byte_count: usize) -> Self {
+        Self { char_count, byte_count }
+    }
+}
+
+/// Returns the number of chars that match from the start
+///
+/// ```
+/// assert_eq!(count_match_start("hello_mouse", "hello_penguin"), StrCount::new(6, 6));
+/// assert_eq!(count_match_start("hello_clippy", "bye_bugs"), StrCount::new(0, 0));
+/// assert_eq!(count_match_start("hello_world", "hello_world"), StrCount::new(11, 11));
+/// assert_eq!(count_match_start("T\u{f6}ffT\u{f6}ff", "T\u{f6}ff"), StrCount::new(4, 5));
+/// ```
+#[must_use]
+pub fn count_match_start(str1: &str, str2: &str) -> StrCount {
+    // (char_index, char1)
+    let char_count = str1.chars().count();
+    let iter1 = (0..=char_count).zip(str1.chars());
+    // (byte_index, char2)
+    let iter2 = str2.char_indices();
+
+    iter1
+        .zip(iter2)
+        .take_while(|((_, c1), (_, c2))| c1 == c2)
+        .last()
+        .map_or_else(StrCount::default, |((char_index, _), (byte_index, character))| {
+            StrCount::new(char_index + 1, byte_index + character.len_utf8())
+        })
+}
+
+/// Returns the number of chars and bytes that match from the end
+///
+/// ```
+/// assert_eq!(count_match_end("hello_cat", "bye_cat"), StrCount::new(4, 4));
+/// assert_eq!(count_match_end("if_item_thing", "enum_value"), StrCount::new(0, 0));
+/// assert_eq!(count_match_end("Clippy", "Clippy"), StrCount::new(6, 6));
+/// assert_eq!(count_match_end("MyT\u{f6}ff", "YourT\u{f6}ff"), StrCount::new(4, 5));
+/// ```
+#[must_use]
+pub fn count_match_end(str1: &str, str2: &str) -> StrCount {
+    let char_count = str1.chars().count();
+    if char_count == 0 {
+        return StrCount::default();
+    }
+
+    // (char_index, char1)
+    let iter1 = (0..char_count).rev().zip(str1.chars().rev());
+    // (byte_index, char2)
+    let byte_count = str2.len();
+    let iter2 = str2.char_indices().rev();
+
+    iter1
+        .zip(iter2)
+        .take_while(|((_, c1), (_, c2))| c1 == c2)
+        .last()
+        .map_or_else(StrCount::default, |((char_index, _), (byte_index, _))| {
+            StrCount::new(char_count - char_index, byte_count - byte_index)
+        })
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn camel_case_start_full() {
+        assert_eq!(camel_case_start("AbcDef"), StrIndex::new(0, 0));
+        assert_eq!(camel_case_start("Abc"), StrIndex::new(0, 0));
+        assert_eq!(camel_case_start("ABcd"), StrIndex::new(0, 0));
+        assert_eq!(camel_case_start("ABcdEf"), StrIndex::new(0, 0));
+        assert_eq!(camel_case_start("AabABcd"), StrIndex::new(0, 0));
+    }
+
+    #[test]
+    fn camel_case_start_partial() {
+        assert_eq!(camel_case_start("abcDef"), StrIndex::new(3, 3));
+        assert_eq!(camel_case_start("aDbc"), StrIndex::new(1, 1));
+        assert_eq!(camel_case_start("aabABcd"), StrIndex::new(3, 3));
+        assert_eq!(camel_case_start("\u{f6}\u{f6}AabABcd"), StrIndex::new(2, 4));
+    }
+
+    #[test]
+    fn camel_case_start_not() {
+        assert_eq!(camel_case_start("AbcDef_"), StrIndex::new(7, 7));
+        assert_eq!(camel_case_start("AbcDD"), StrIndex::new(5, 5));
+        assert_eq!(camel_case_start("all_small"), StrIndex::new(9, 9));
+        assert_eq!(camel_case_start("\u{f6}_all_small"), StrIndex::new(11, 12));
+    }
+
+    #[test]
+    fn camel_case_start_caps() {
+        assert_eq!(camel_case_start("ABCD"), StrIndex::new(4, 4));
+    }
+
+    #[test]
+    fn camel_case_until_full() {
+        assert_eq!(camel_case_until("AbcDef"), StrIndex::new(6, 6));
+        assert_eq!(camel_case_until("Abc"), StrIndex::new(3, 3));
+        assert_eq!(camel_case_until("Abc\u{f6}\u{f6}\u{f6}"), StrIndex::new(6, 9));
+    }
+
+    #[test]
+    fn camel_case_until_not() {
+        assert_eq!(camel_case_until("abcDef"), StrIndex::new(0, 0));
+        assert_eq!(camel_case_until("aDbc"), StrIndex::new(0, 0));
+    }
+
+    #[test]
+    fn camel_case_until_partial() {
+        assert_eq!(camel_case_until("AbcDef_"), StrIndex::new(6, 6));
+        assert_eq!(camel_case_until("CallTypeC"), StrIndex::new(8, 8));
+        assert_eq!(camel_case_until("AbcDD"), StrIndex::new(3, 3));
+        assert_eq!(camel_case_until("Abc\u{f6}\u{f6}DD"), StrIndex::new(5, 7));
+    }
+
+    #[test]
+    fn until_caps() {
+        assert_eq!(camel_case_until("ABCD"), StrIndex::new(0, 0));
+    }
+}
diff --git a/src/tools/clippy/doc/adding_lints.md b/src/tools/clippy/doc/adding_lints.md
index 004eb28b446..bd32696d6db 100644
--- a/src/tools/clippy/doc/adding_lints.md
+++ b/src/tools/clippy/doc/adding_lints.md
@@ -16,6 +16,7 @@ because that's clearly a non-descriptive name.
   - [Edition 2018 tests](#edition-2018-tests)
   - [Testing manually](#testing-manually)
   - [Lint declaration](#lint-declaration)
+  - [Lint registration](#lint-registration)
   - [Lint passes](#lint-passes)
   - [Emitting a lint](#emitting-a-lint)
   - [Adding the lint logic](#adding-the-lint-logic)
@@ -43,9 +44,9 @@ take a look at our [lint naming guidelines][lint_naming]. To get started on this
 lint you can run `cargo dev new_lint --name=foo_functions --pass=early
 --category=pedantic` (category will default to nursery if not provided). This
 command will create two files: `tests/ui/foo_functions.rs` and
-`clippy_lints/src/foo_functions.rs`, as well as run `cargo dev update_lints` to
-register the new lint. For cargo lints, two project hierarchies (fail/pass) will
-be created by default under `tests/ui-cargo`.
+`clippy_lints/src/foo_functions.rs`, as well as
+[registering the lint](#lint-registration). For cargo lints, two project
+hierarchies (fail/pass) will be created by default under `tests/ui-cargo`.
 
 Next, we'll open up these files and add our lint!
 
@@ -220,32 +221,34 @@ declare_lint_pass!(FooFunctions => [FOO_FUNCTIONS]);
 impl EarlyLintPass for FooFunctions {}
 ```
 
-Normally after declaring the lint, we have to run `cargo dev update_lints`,
-which updates some files, so Clippy knows about the new lint. Since we used
-`cargo dev new_lint ...` to generate the lint declaration, this was done
-automatically. While `update_lints` automates most of the things, it doesn't
-automate everything. We will have to register our lint pass manually in the
-`register_plugins` function in `clippy_lints/src/lib.rs`:
+[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60
+[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
+[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
+[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110
+
+## Lint registration
+
+When using `cargo dev new_lint`, the lint is automatically registered and
+nothing more has to be done.
+
+When declaring a new lint by hand and `cargo dev update_lints` is used, the lint
+pass may have to be registered manually in the `register_plugins` function in
+`clippy_lints/src/lib.rs`:
 
 ```rust
-store.register_early_pass(|| box foo_functions::FooFunctions);
+store.register_early_pass(|| Box::new(foo_functions::FooFunctions));
 ```
 
 As one may expect, there is a corresponding `register_late_pass` method
 available as well. Without a call to one of `register_early_pass` or
 `register_late_pass`, the lint pass in question will not be run.
 
-One reason that `cargo dev` does not automate this step is that multiple lints
-can use the same lint pass, so registering the lint pass may already be done
-when adding a new lint. Another reason that this step is not automated is that
-the order that the passes are registered determines the order the passes
-actually run, which in turn affects the order that any emitted lints are output
-in.
-
-[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60
-[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
-[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
-[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110
+One reason that `cargo dev update_lints` does not automate this step is that
+multiple lints can use the same lint pass, so registering the lint pass may
+already be done when adding a new lint. Another reason that this step is not
+automated is that the order that the passes are registered determines the order
+the passes actually run, which in turn affects the order that any emitted lints
+are output in.
 
 ## Lint passes
 
@@ -564,7 +567,8 @@ in the following steps:
     /// <The configuration field doc comment>
     (configuration_ident: Type = DefaultValue),
     ```
-    The doc comment will be automatically added to the lint documentation.
+    The doc comment is automatically added to the documentation of the listed lints. The default
+    value will be formatted using the `Debug` implementation of the type.
 2. Adding the configuration value to the lint impl struct:
     1. This first requires the definition of a lint impl struct. Lint impl structs are usually
         generated with the `declare_lint_pass!` macro. This struct needs to be defined manually
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 67eaf286004..09554c08987 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-10-21"
+channel = "nightly-2021-11-04"
 components = ["llvm-tools-preview", "rustc-dev", "rust-src"]
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index c15835ef299..f25cf1d3ef5 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -104,7 +104,10 @@ fn extern_flags() -> String {
 }
 
 fn default_config() -> compiletest::Config {
-    let mut config = compiletest::Config::default();
+    let mut config = compiletest::Config {
+        edition: Some("2021".into()),
+        ..compiletest::Config::default()
+    };
 
     if let Ok(filters) = env::var("TESTNAME") {
         config.filters = filters.split(',').map(std::string::ToString::to_string).collect();
diff --git a/src/tools/clippy/tests/missing-test-files.rs b/src/tools/clippy/tests/missing-test-files.rs
index bd342e390f5..7d6edc2b1e0 100644
--- a/src/tools/clippy/tests/missing-test-files.rs
+++ b/src/tools/clippy/tests/missing-test-files.rs
@@ -1,7 +1,10 @@
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![warn(rust_2018_idioms, unused_lifetimes)]
 #![allow(clippy::assertions_on_constants)]
+#![feature(path_file_prefix)]
 
+use std::cmp::Ordering;
+use std::ffi::OsStr;
 use std::fs::{self, DirEntry};
 use std::path::Path;
 
@@ -21,29 +24,39 @@ fn test_missing_tests() {
     }
 }
 
-/*
-Test for missing files.
-
-Since rs files are alphabetically before stderr/stdout, we can sort by the full name
-and iter in that order. If we've seen the file stem for the first time and it's not
-a rust file, it means the rust file has to be missing.
-*/
+// Test for missing files.
 fn explore_directory(dir: &Path) -> Vec<String> {
     let mut missing_files: Vec<String> = Vec::new();
     let mut current_file = String::new();
     let mut files: Vec<DirEntry> = fs::read_dir(dir).unwrap().filter_map(Result::ok).collect();
-    files.sort_by_key(std::fs::DirEntry::path);
+    files.sort_by(|x, y| {
+        match x.path().file_prefix().cmp(&y.path().file_prefix()) {
+            Ordering::Equal => (),
+            ord => return ord,
+        }
+        // Sort rs files before the others if they share the same prefix. So when we see
+        // the file prefix for the first time and it's not a rust file, it means the rust
+        // file has to be missing.
+        match (
+            x.path().extension().and_then(OsStr::to_str),
+            y.path().extension().and_then(OsStr::to_str),
+        ) {
+            (Some("rs"), _) => Ordering::Less,
+            (_, Some("rs")) => Ordering::Greater,
+            _ => Ordering::Equal,
+        }
+    });
     for entry in &files {
         let path = entry.path();
         if path.is_dir() {
             missing_files.extend(explore_directory(&path));
         } else {
-            let file_stem = path.file_stem().unwrap().to_str().unwrap().to_string();
+            let file_prefix = path.file_prefix().unwrap().to_str().unwrap().to_string();
             if let Some(ext) = path.extension() {
                 match ext.to_str().unwrap() {
-                    "rs" => current_file = file_stem.clone(),
+                    "rs" => current_file = file_prefix.clone(),
                     "stderr" | "stdout" => {
-                        if file_stem != current_file {
+                        if file_prefix != current_file {
                             missing_files.push(path.to_str().unwrap().to_string());
                         }
                     },
diff --git a/src/tools/clippy/tests/ui-toml/functions_maxlines/test.rs b/src/tools/clippy/tests/ui-toml/functions_maxlines/test.rs
index 33a3ef75136..e678c896fd3 100644
--- a/src/tools/clippy/tests/ui-toml/functions_maxlines/test.rs
+++ b/src/tools/clippy/tests/ui-toml/functions_maxlines/test.rs
@@ -1,5 +1,3 @@
-// edition:2018
-
 #![warn(clippy::too_many_lines)]
 
 // This function should be considered one line.
diff --git a/src/tools/clippy/tests/ui-toml/functions_maxlines/test.stderr b/src/tools/clippy/tests/ui-toml/functions_maxlines/test.stderr
index 7551cac9f50..d736bf89973 100644
--- a/src/tools/clippy/tests/ui-toml/functions_maxlines/test.stderr
+++ b/src/tools/clippy/tests/ui-toml/functions_maxlines/test.stderr
@@ -1,5 +1,5 @@
 error: this function has too many lines (2/1)
-  --> $DIR/test.rs:20:1
+  --> $DIR/test.rs:18:1
    |
 LL | / fn too_many_lines() {
 LL | |     println!("This is bad.");
@@ -10,7 +10,7 @@ LL | | }
    = note: `-D clippy::too-many-lines` implied by `-D warnings`
 
 error: this function has too many lines (4/1)
-  --> $DIR/test.rs:26:1
+  --> $DIR/test.rs:24:1
    |
 LL | / async fn async_too_many_lines() {
 LL | |     println!("This is bad.");
@@ -19,7 +19,7 @@ LL | | }
    | |_^
 
 error: this function has too many lines (4/1)
-  --> $DIR/test.rs:32:1
+  --> $DIR/test.rs:30:1
    |
 LL | / fn closure_too_many_lines() {
 LL | |     let _ = {
@@ -30,7 +30,7 @@ LL | | }
    | |_^
 
 error: this function has too many lines (2/1)
-  --> $DIR/test.rs:54:1
+  --> $DIR/test.rs:52:1
    |
 LL | / fn comment_before_code() {
 LL | |     let _ = "test";
diff --git a/src/tools/clippy/tests/ui/assertions_on_constants.rs b/src/tools/clippy/tests/ui/assertions_on_constants.rs
index 2180f848d62..cb516d0f977 100644
--- a/src/tools/clippy/tests/ui/assertions_on_constants.rs
+++ b/src/tools/clippy/tests/ui/assertions_on_constants.rs
@@ -1,3 +1,4 @@
+//FIXME: suggestions are wrongly expanded, this should be fixed along with #7843
 #![allow(non_fmt_panics)]
 
 macro_rules! assert_const {
@@ -6,7 +7,6 @@ macro_rules! assert_const {
         debug_assert!($len < 0);
     };
 }
-
 fn main() {
     assert!(true);
     assert!(false);
@@ -14,7 +14,7 @@ fn main() {
     assert!(false, "false message");
 
     let msg = "panic message";
-    assert!(false, msg.to_uppercase());
+    assert!(false, "{}", msg.to_uppercase());
 
     const B: bool = true;
     assert!(B);
diff --git a/src/tools/clippy/tests/ui/assertions_on_constants.stderr b/src/tools/clippy/tests/ui/assertions_on_constants.stderr
index 4ca1e6f6e88..ec80ec702fb 100644
--- a/src/tools/clippy/tests/ui/assertions_on_constants.stderr
+++ b/src/tools/clippy/tests/ui/assertions_on_constants.stderr
@@ -26,22 +26,13 @@ LL |     assert!(true, "true message");
    = help: remove it
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: `assert!(false, "false message")` should probably be replaced
+error: `assert!(false, $crate::const_format_args!($($t)+))` should probably be replaced
   --> $DIR/assertions_on_constants.rs:14:5
    |
 LL |     assert!(false, "false message");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: use `panic!("false message")` or `unreachable!("false message")`
-   = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: `assert!(false, msg.to_uppercase())` should probably be replaced
-  --> $DIR/assertions_on_constants.rs:17:5
-   |
-LL |     assert!(false, msg.to_uppercase());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: use `panic!(msg.to_uppercase())` or `unreachable!(msg.to_uppercase())`
+   = help: use `panic!($crate::const_format_args!($($t)+))` or `unreachable!($crate::const_format_args!($($t)+))`
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `assert!(true)` will be optimized out by the compiler
@@ -62,13 +53,13 @@ LL |     assert!(C);
    = help: use `panic!()` or `unreachable!()`
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: `assert!(false, "C message")` should probably be replaced
+error: `assert!(false, $crate::const_format_args!($($t)+))` should probably be replaced
   --> $DIR/assertions_on_constants.rs:24:5
    |
 LL |     assert!(C, "C message");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: use `panic!("C message")` or `unreachable!("C message")`
+   = help: use `panic!($crate::const_format_args!($($t)+))` or `unreachable!($crate::const_format_args!($($t)+))`
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `debug_assert!(true)` will be optimized out by the compiler
@@ -80,5 +71,5 @@ LL |     debug_assert!(true);
    = help: remove it
    = note: this error originates in the macro `$crate::assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/async_yields_async.fixed b/src/tools/clippy/tests/ui/async_yields_async.fixed
index 9b1a7ac3ba9..e20b58269b9 100644
--- a/src/tools/clippy/tests/ui/async_yields_async.fixed
+++ b/src/tools/clippy/tests/ui/async_yields_async.fixed
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 
 #![feature(async_closure)]
 #![warn(clippy::async_yields_async)]
diff --git a/src/tools/clippy/tests/ui/async_yields_async.rs b/src/tools/clippy/tests/ui/async_yields_async.rs
index 731c094edb4..c1dfa398450 100644
--- a/src/tools/clippy/tests/ui/async_yields_async.rs
+++ b/src/tools/clippy/tests/ui/async_yields_async.rs
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 
 #![feature(async_closure)]
 #![warn(clippy::async_yields_async)]
diff --git a/src/tools/clippy/tests/ui/async_yields_async.stderr b/src/tools/clippy/tests/ui/async_yields_async.stderr
index 3f2051458f6..b0c4215e7dd 100644
--- a/src/tools/clippy/tests/ui/async_yields_async.stderr
+++ b/src/tools/clippy/tests/ui/async_yields_async.stderr
@@ -1,5 +1,5 @@
 error: an async construct yields a type which is itself awaitable
-  --> $DIR/async_yields_async.rs:40:9
+  --> $DIR/async_yields_async.rs:39:9
    |
 LL |        let _h = async {
    |   ____________________-
@@ -20,7 +20,7 @@ LL +         }.await
    |
 
 error: an async construct yields a type which is itself awaitable
-  --> $DIR/async_yields_async.rs:45:9
+  --> $DIR/async_yields_async.rs:44:9
    |
 LL |       let _i = async {
    |  ____________________-
@@ -33,7 +33,7 @@ LL | |     };
    | |_____- outer async construct
 
 error: an async construct yields a type which is itself awaitable
-  --> $DIR/async_yields_async.rs:51:9
+  --> $DIR/async_yields_async.rs:50:9
    |
 LL |        let _j = async || {
    |   _______________________-
@@ -53,7 +53,7 @@ LL +         }.await
    |
 
 error: an async construct yields a type which is itself awaitable
-  --> $DIR/async_yields_async.rs:56:9
+  --> $DIR/async_yields_async.rs:55:9
    |
 LL |       let _k = async || {
    |  _______________________-
@@ -66,7 +66,7 @@ LL | |     };
    | |_____- outer async construct
 
 error: an async construct yields a type which is itself awaitable
-  --> $DIR/async_yields_async.rs:58:23
+  --> $DIR/async_yields_async.rs:57:23
    |
 LL |     let _l = async || CustomFutureType;
    |                       ^^^^^^^^^^^^^^^^
@@ -76,7 +76,7 @@ LL |     let _l = async || CustomFutureType;
    |                       help: consider awaiting this value: `CustomFutureType.await`
 
 error: an async construct yields a type which is itself awaitable
-  --> $DIR/async_yields_async.rs:64:9
+  --> $DIR/async_yields_async.rs:63:9
    |
 LL |       let _m = async || {
    |  _______________________-
diff --git a/src/tools/clippy/tests/ui/await_holding_lock.rs b/src/tools/clippy/tests/ui/await_holding_lock.rs
index 0458950edee..dd6640a387a 100644
--- a/src/tools/clippy/tests/ui/await_holding_lock.rs
+++ b/src/tools/clippy/tests/ui/await_holding_lock.rs
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::await_holding_lock)]
 
 use std::sync::Mutex;
diff --git a/src/tools/clippy/tests/ui/await_holding_lock.stderr b/src/tools/clippy/tests/ui/await_holding_lock.stderr
index a5fcff7e0e4..ddfb104cdfb 100644
--- a/src/tools/clippy/tests/ui/await_holding_lock.stderr
+++ b/src/tools/clippy/tests/ui/await_holding_lock.stderr
@@ -1,12 +1,12 @@
 error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
-  --> $DIR/await_holding_lock.rs:7:9
+  --> $DIR/await_holding_lock.rs:6:9
    |
 LL |     let guard = x.lock().unwrap();
    |         ^^^^^
    |
    = note: `-D clippy::await-holding-lock` implied by `-D warnings`
 note: these are all the await points this lock is held through
-  --> $DIR/await_holding_lock.rs:7:5
+  --> $DIR/await_holding_lock.rs:6:5
    |
 LL | /     let guard = x.lock().unwrap();
 LL | |     baz().await
@@ -14,13 +14,13 @@ LL | | }
    | |_^
 
 error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
-  --> $DIR/await_holding_lock.rs:28:9
+  --> $DIR/await_holding_lock.rs:27:9
    |
 LL |     let guard = x.lock().unwrap();
    |         ^^^^^
    |
 note: these are all the await points this lock is held through
-  --> $DIR/await_holding_lock.rs:28:5
+  --> $DIR/await_holding_lock.rs:27:5
    |
 LL | /     let guard = x.lock().unwrap();
 LL | |
@@ -32,13 +32,13 @@ LL | | }
    | |_^
 
 error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
-  --> $DIR/await_holding_lock.rs:41:13
+  --> $DIR/await_holding_lock.rs:40:13
    |
 LL |         let guard = x.lock().unwrap();
    |             ^^^^^
    |
 note: these are all the await points this lock is held through
-  --> $DIR/await_holding_lock.rs:41:9
+  --> $DIR/await_holding_lock.rs:40:9
    |
 LL | /         let guard = x.lock().unwrap();
 LL | |         baz().await
@@ -46,13 +46,13 @@ LL | |     };
    | |_____^
 
 error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
-  --> $DIR/await_holding_lock.rs:53:13
+  --> $DIR/await_holding_lock.rs:52:13
    |
 LL |         let guard = x.lock().unwrap();
    |             ^^^^^
    |
 note: these are all the await points this lock is held through
-  --> $DIR/await_holding_lock.rs:53:9
+  --> $DIR/await_holding_lock.rs:52:9
    |
 LL | /         let guard = x.lock().unwrap();
 LL | |         baz().await
diff --git a/src/tools/clippy/tests/ui/await_holding_refcell_ref.rs b/src/tools/clippy/tests/ui/await_holding_refcell_ref.rs
index 88841597bb6..23b7095de3a 100644
--- a/src/tools/clippy/tests/ui/await_holding_refcell_ref.rs
+++ b/src/tools/clippy/tests/ui/await_holding_refcell_ref.rs
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::await_holding_refcell_ref)]
 
 use std::cell::RefCell;
diff --git a/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr b/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr
index 55e41dbca96..67cc0032be2 100644
--- a/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr
+++ b/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr
@@ -1,12 +1,12 @@
 error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
-  --> $DIR/await_holding_refcell_ref.rs:7:9
+  --> $DIR/await_holding_refcell_ref.rs:6:9
    |
 LL |     let b = x.borrow();
    |         ^
    |
    = note: `-D clippy::await-holding-refcell-ref` implied by `-D warnings`
 note: these are all the await points this ref is held through
-  --> $DIR/await_holding_refcell_ref.rs:7:5
+  --> $DIR/await_holding_refcell_ref.rs:6:5
    |
 LL | /     let b = x.borrow();
 LL | |     baz().await
@@ -14,13 +14,13 @@ LL | | }
    | |_^
 
 error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
-  --> $DIR/await_holding_refcell_ref.rs:12:9
+  --> $DIR/await_holding_refcell_ref.rs:11:9
    |
 LL |     let b = x.borrow_mut();
    |         ^
    |
 note: these are all the await points this ref is held through
-  --> $DIR/await_holding_refcell_ref.rs:12:5
+  --> $DIR/await_holding_refcell_ref.rs:11:5
    |
 LL | /     let b = x.borrow_mut();
 LL | |     baz().await
@@ -28,13 +28,13 @@ LL | | }
    | |_^
 
 error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
-  --> $DIR/await_holding_refcell_ref.rs:33:9
+  --> $DIR/await_holding_refcell_ref.rs:32:9
    |
 LL |     let b = x.borrow_mut();
    |         ^
    |
 note: these are all the await points this ref is held through
-  --> $DIR/await_holding_refcell_ref.rs:33:5
+  --> $DIR/await_holding_refcell_ref.rs:32:5
    |
 LL | /     let b = x.borrow_mut();
 LL | |
@@ -46,13 +46,13 @@ LL | | }
    | |_^
 
 error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
-  --> $DIR/await_holding_refcell_ref.rs:45:9
+  --> $DIR/await_holding_refcell_ref.rs:44:9
    |
 LL |     let b = x.borrow_mut();
    |         ^
    |
 note: these are all the await points this ref is held through
-  --> $DIR/await_holding_refcell_ref.rs:45:5
+  --> $DIR/await_holding_refcell_ref.rs:44:5
    |
 LL | /     let b = x.borrow_mut();
 LL | |
@@ -64,13 +64,13 @@ LL | | }
    | |_^
 
 error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
-  --> $DIR/await_holding_refcell_ref.rs:60:13
+  --> $DIR/await_holding_refcell_ref.rs:59:13
    |
 LL |         let b = x.borrow_mut();
    |             ^
    |
 note: these are all the await points this ref is held through
-  --> $DIR/await_holding_refcell_ref.rs:60:9
+  --> $DIR/await_holding_refcell_ref.rs:59:9
    |
 LL | /         let b = x.borrow_mut();
 LL | |         baz().await
@@ -78,13 +78,13 @@ LL | |     };
    | |_____^
 
 error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
-  --> $DIR/await_holding_refcell_ref.rs:72:13
+  --> $DIR/await_holding_refcell_ref.rs:71:13
    |
 LL |         let b = x.borrow_mut();
    |             ^
    |
 note: these are all the await points this ref is held through
-  --> $DIR/await_holding_refcell_ref.rs:72:9
+  --> $DIR/await_holding_refcell_ref.rs:71:9
    |
 LL | /         let b = x.borrow_mut();
 LL | |         baz().await
diff --git a/src/tools/clippy/tests/ui/cast.rs b/src/tools/clippy/tests/ui/cast.rs
index 8ee0969b0f0..ebc1ed5587f 100644
--- a/src/tools/clippy/tests/ui/cast.rs
+++ b/src/tools/clippy/tests/ui/cast.rs
@@ -92,4 +92,27 @@ fn main() {
     (1i64).checked_rem_euclid(-1i64).unwrap() as u64;
     (1i64).checked_rem_euclid(-1i64).unwrap() as u128;
     (1isize).checked_rem_euclid(-1isize).unwrap() as usize;
+
+    // no lint for `cast_possible_truncation`
+    // with `signum` method call (see issue #5395)
+    let x: i64 = 5;
+    let _ = x.signum() as i32;
+
+    let s = x.signum();
+    let _ = s as i32;
+
+    // Test for signed min
+    (-99999999999i64).min(1) as i8; // should be linted because signed
+
+    // Test for various operations that remove enough bits for the result to fit
+    (999999u64 & 1) as u8;
+    (999999u64 % 15) as u8;
+    (999999u64 / 0x1_0000_0000_0000) as u16;
+    ({ 999999u64 >> 56 }) as u8;
+    ({
+        let x = 999999u64;
+        x.min(1)
+    }) as u8;
+    999999u64.clamp(0, 255) as u8;
+    999999u64.clamp(0, 256) as u8; // should still be linted
 }
diff --git a/src/tools/clippy/tests/ui/cast.stderr b/src/tools/clippy/tests/ui/cast.stderr
index 4c66d736494..edf8790cf33 100644
--- a/src/tools/clippy/tests/ui/cast.stderr
+++ b/src/tools/clippy/tests/ui/cast.stderr
@@ -138,5 +138,17 @@ error: casting `isize` to `usize` may lose the sign of the value
 LL |     -1isize as usize;
    |     ^^^^^^^^^^^^^^^^
 
-error: aborting due to 22 previous errors
+error: casting `i64` to `i8` may truncate the value
+  --> $DIR/cast.rs:105:5
+   |
+LL |     (-99999999999i64).min(1) as i8; // should be linted because signed
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `u64` to `u8` may truncate the value
+  --> $DIR/cast.rs:117:5
+   |
+LL |     999999u64.clamp(0, 256) as u8; // should still be linted
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 24 previous errors
 
diff --git a/src/tools/clippy/tests/ui/crashes/auxiliary/ice-7868-aux.rs b/src/tools/clippy/tests/ui/crashes/auxiliary/ice-7868-aux.rs
new file mode 100644
index 00000000000..bee29894b63
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/auxiliary/ice-7868-aux.rs
@@ -0,0 +1,3 @@
+fn zero() {
+    unsafe { 0 };
+}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-3969.rs b/src/tools/clippy/tests/ui/crashes/ice-3969.rs
index 4feab7910b7..9b68cac7ff4 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-3969.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-3969.rs
@@ -7,7 +7,6 @@
 // in type inference.
 #![feature(trivial_bounds)]
 #![allow(unused)]
-
 trait A {}
 
 impl A for i32 {}
@@ -22,9 +21,9 @@ where
 
 fn unsized_local()
 where
-    for<'a> Dst<A + 'a>: Sized,
+    for<'a> Dst<dyn A + 'a>: Sized,
 {
-    let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
+    let x: Dst<dyn A> = *(Box::new(Dst { x: 1 }) as Box<Dst<dyn A>>);
 }
 
 fn return_str() -> str
diff --git a/src/tools/clippy/tests/ui/crashes/ice-3969.stderr b/src/tools/clippy/tests/ui/crashes/ice-3969.stderr
index 9a89047f072..79018080886 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-3969.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-3969.stderr
@@ -1,30 +1,34 @@
-error: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/ice-3969.rs:25:17
+error: trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
+  --> $DIR/ice-3969.rs:20:10
    |
-LL |     for<'a> Dst<A + 'a>: Sized,
-   |                 ^^^^^^ help: use `dyn`: `dyn A + 'a`
+LL |     str: Sized;
+   |          ^^^^^
    |
-   = note: `-D bare-trait-objects` implied by `-D warnings`
-   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `-D trivial-bounds` implied by `-D warnings`
 
-error: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/ice-3969.rs:27:16
+error: trait bound for<'a> Dst<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters
+  --> $DIR/ice-3969.rs:24:30
    |
-LL |     let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
-   |                ^ help: use `dyn`: `dyn A`
+LL |     for<'a> Dst<dyn A + 'a>: Sized,
+   |                              ^^^^^
+
+error: trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
+  --> $DIR/ice-3969.rs:31:10
    |
-   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+LL |     str: Sized,
+   |          ^^^^^
 
-error: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/ice-3969.rs:27:57
+error: trait bound std::string::String: std::ops::Neg does not depend on any type or lifetime parameters
+  --> $DIR/ice-3969.rs:38:13
    |
-LL |     let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
-   |                                                         ^ help: use `dyn`: `dyn A`
+LL |     String: ::std::ops::Neg<Output = String>,
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bound i32: std::iter::Iterator does not depend on any type or lifetime parameters
+  --> $DIR/ice-3969.rs:45:10
    |
-   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+LL |     i32: Iterator,
+   |          ^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-5207.rs b/src/tools/clippy/tests/ui/crashes/ice-5207.rs
index 1b20c9defac..f463f78a99a 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-5207.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-5207.rs
@@ -1,5 +1,3 @@
-// edition:2018
-
 // Regression test for https://github.com/rust-lang/rust-clippy/issues/5207
 
 pub async fn bar<'a, T: 'a>(_: T) {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6252.rs b/src/tools/clippy/tests/ui/crashes/ice-6252.rs
index 2e3d9fd1e92..0ccf0aae9d7 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6252.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-6252.rs
@@ -1,6 +1,5 @@
 // originally from glacier fixed/77919.rs
 // encountered errors resolving bounds after type-checking
-
 trait TypeVal<T> {
     const VAL: T;
 }
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
index eaa5e6f51cb..c8239897f3a 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
@@ -1,16 +1,20 @@
 error[E0412]: cannot find type `PhantomData` in this scope
-  --> $DIR/ice-6252.rs:9:9
+  --> $DIR/ice-6252.rs:8:9
    |
 LL |     _n: PhantomData,
    |         ^^^^^^^^^^^ not found in this scope
    |
-help: consider importing this struct
+help: consider importing one of these items
+   |
+LL | use core::marker::PhantomData;
+   |
+LL | use serde::__private::PhantomData;
    |
 LL | use std::marker::PhantomData;
    |
 
 error[E0412]: cannot find type `VAL` in this scope
-  --> $DIR/ice-6252.rs:11:63
+  --> $DIR/ice-6252.rs:10:63
    |
 LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
    |          -                                                    ^^^ not found in this scope
@@ -18,7 +22,7 @@ LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
    |          help: you might be missing a type parameter: `, VAL`
 
 error[E0046]: not all trait items implemented, missing: `VAL`
-  --> $DIR/ice-6252.rs:11:1
+  --> $DIR/ice-6252.rs:10:1
    |
 LL |     const VAL: T;
    |     ------------- `VAL` from trait
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7231.rs b/src/tools/clippy/tests/ui/crashes/ice-7231.rs
index 5595d8d1d62..4ad0d351372 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-7231.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-7231.rs
@@ -1,4 +1,3 @@
-// edition:2018
 #![allow(clippy::never_loop)]
 
 async fn f() {
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7868.rs b/src/tools/clippy/tests/ui/crashes/ice-7868.rs
new file mode 100644
index 00000000000..c6932164e3b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-7868.rs
@@ -0,0 +1,7 @@
+#![warn(clippy::undocumented_unsafe_blocks)]
+#![allow(clippy::no_effect)]
+
+#[path = "auxiliary/ice-7868-aux.rs"]
+mod zero;
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7868.stderr b/src/tools/clippy/tests/ui/crashes/ice-7868.stderr
new file mode 100644
index 00000000000..d7b49eb89a2
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-7868.stderr
@@ -0,0 +1,15 @@
+error: unsafe block missing a safety comment
+  --> $DIR/auxiliary/ice-7868-aux.rs:2:5
+   |
+LL |     unsafe { 0 };
+   |     ^^^^^^^^^^^^
+   |
+   = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings`
+help: consider adding a safety comment
+   |
+LL ~     // Safety: ...
+LL ~     unsafe { 0 };
+   |
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7869.rs b/src/tools/clippy/tests/ui/crashes/ice-7869.rs
new file mode 100644
index 00000000000..8f97a063a9a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-7869.rs
@@ -0,0 +1,7 @@
+enum Tila {
+    TyöAlkoi,
+    TyöKeskeytyi,
+    TyöValmis,
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7869.stderr b/src/tools/clippy/tests/ui/crashes/ice-7869.stderr
new file mode 100644
index 00000000000..4fa9fb27e76
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-7869.stderr
@@ -0,0 +1,15 @@
+error: all variants have the same prefix: `Työ`
+  --> $DIR/ice-7869.rs:1:1
+   |
+LL | / enum Tila {
+LL | |     TyöAlkoi,
+LL | |     TyöKeskeytyi,
+LL | |     TyöValmis,
+LL | | }
+   | |_^
+   |
+   = note: `-D clippy::enum-variant-names` implied by `-D warnings`
+   = help: remove the prefixes and use full paths to the variants instead of glob imports
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/crashes/used_underscore_binding_macro.rs b/src/tools/clippy/tests/ui/crashes/used_underscore_binding_macro.rs
index c57a45dc7aa..901eb4e5039 100644
--- a/src/tools/clippy/tests/ui/crashes/used_underscore_binding_macro.rs
+++ b/src/tools/clippy/tests/ui/crashes/used_underscore_binding_macro.rs
@@ -1,5 +1,3 @@
-// edition:2018
-
 use serde::Deserialize;
 
 /// Tests that we do not lint for unused underscores in a `MacroAttribute`
diff --git a/src/tools/clippy/tests/ui/debug_assert_with_mut_call.rs b/src/tools/clippy/tests/ui/debug_assert_with_mut_call.rs
index 477a47118d4..c5de4125565 100644
--- a/src/tools/clippy/tests/ui/debug_assert_with_mut_call.rs
+++ b/src/tools/clippy/tests/ui/debug_assert_with_mut_call.rs
@@ -1,9 +1,9 @@
-// compile-flags: --edition=2018
 #![feature(custom_inner_attributes)]
 #![rustfmt::skip]
 #![warn(clippy::debug_assert_with_mut_call)]
 #![allow(clippy::redundant_closure_call)]
 
+
 struct S;
 
 impl S {
diff --git a/src/tools/clippy/tests/ui/deprecated.rs b/src/tools/clippy/tests/ui/deprecated.rs
index 1943d0092e6..39a2601fee9 100644
--- a/src/tools/clippy/tests/ui/deprecated.rs
+++ b/src/tools/clippy/tests/ui/deprecated.rs
@@ -1,19 +1,18 @@
-#[warn(clippy::unstable_as_slice)]
-#[warn(clippy::unstable_as_mut_slice)]
-#[warn(clippy::misaligned_transmute)]
-#[warn(clippy::unused_collect)]
-#[warn(clippy::invalid_ref)]
-#[warn(clippy::into_iter_on_array)]
-#[warn(clippy::unused_label)]
-#[warn(clippy::regex_macro)]
-#[warn(clippy::drop_bounds)]
-#[warn(clippy::temporary_cstring_as_ptr)]
-#[warn(clippy::panic_params)]
-#[warn(clippy::unknown_clippy_lints)]
-#[warn(clippy::find_map)]
-#[warn(clippy::filter_map)]
-#[warn(clippy::pub_enum_variant_names)]
-#[warn(clippy::wrong_pub_self_convention)]
-#[warn(clippy::invalid_atomic_ordering)]
+#![warn(clippy::should_assert_eq)]
+#![warn(clippy::extend_from_slice)]
+#![warn(clippy::range_step_by_zero)]
+#![warn(clippy::unstable_as_slice)]
+#![warn(clippy::unstable_as_mut_slice)]
+#![warn(clippy::misaligned_transmute)]
+#![warn(clippy::assign_ops)]
+#![warn(clippy::if_let_redundant_pattern_matching)]
+#![warn(clippy::unsafe_vector_initialization)]
+#![warn(clippy::unused_collect)]
+#![warn(clippy::replace_consts)]
+#![warn(clippy::regex_macro)]
+#![warn(clippy::find_map)]
+#![warn(clippy::filter_map)]
+#![warn(clippy::pub_enum_variant_names)]
+#![warn(clippy::wrong_pub_self_convention)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr
index 51048e45c06..6095f134d55 100644
--- a/src/tools/clippy/tests/ui/deprecated.stderr
+++ b/src/tools/clippy/tests/ui/deprecated.stderr
@@ -1,106 +1,100 @@
-error: lint `clippy::unstable_as_slice` has been removed: `Vec::as_slice` has been stabilized in 1.7
-  --> $DIR/deprecated.rs:1:8
+error: lint `clippy::should_assert_eq` has been removed: `assert!()` will be more flexible with RFC 2011
+  --> $DIR/deprecated.rs:1:9
    |
-LL | #[warn(clippy::unstable_as_slice)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::should_assert_eq)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 
-error: lint `clippy::unstable_as_mut_slice` has been removed: `Vec::as_mut_slice` has been stabilized in 1.7
-  --> $DIR/deprecated.rs:2:8
+error: lint `clippy::extend_from_slice` has been removed: `.extend_from_slice(_)` is a faster way to extend a Vec by a slice
+  --> $DIR/deprecated.rs:2:9
    |
-LL | #[warn(clippy::unstable_as_mut_slice)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::extend_from_slice)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::misaligned_transmute` has been removed: this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr
-  --> $DIR/deprecated.rs:3:8
+error: lint `clippy::range_step_by_zero` has been removed: `iterator.step_by(0)` panics nowadays
+  --> $DIR/deprecated.rs:3:9
    |
-LL | #[warn(clippy::misaligned_transmute)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::range_step_by_zero)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::unused_collect` has been removed: `collect` has been marked as #[must_use] in rustc and that covers all cases of this lint
-  --> $DIR/deprecated.rs:4:8
+error: lint `clippy::unstable_as_slice` has been removed: `Vec::as_slice` has been stabilized in 1.7
+  --> $DIR/deprecated.rs:4:9
    |
-LL | #[warn(clippy::unused_collect)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::unstable_as_slice)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/deprecated.rs:5:8
+error: lint `clippy::unstable_as_mut_slice` has been removed: `Vec::as_mut_slice` has been stabilized in 1.7
+  --> $DIR/deprecated.rs:5:9
    |
-LL | #[warn(clippy::invalid_ref)]
-   |        ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
+LL | #![warn(clippy::unstable_as_mut_slice)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/deprecated.rs:6:8
+error: lint `clippy::misaligned_transmute` has been removed: this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr
+  --> $DIR/deprecated.rs:6:9
    |
-LL | #[warn(clippy::into_iter_on_array)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
+LL | #![warn(clippy::misaligned_transmute)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/deprecated.rs:7:8
+error: lint `clippy::assign_ops` has been removed: using compound assignment operators (e.g., `+=`) is harmless
+  --> $DIR/deprecated.rs:7:9
    |
-LL | #[warn(clippy::unused_label)]
-   |        ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
+LL | #![warn(clippy::assign_ops)]
+   |         ^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::regex_macro` has been removed: the regex! macro has been removed from the regex crate in 2018
-  --> $DIR/deprecated.rs:8:8
+error: lint `clippy::if_let_redundant_pattern_matching` has been removed: this lint has been changed to redundant_pattern_matching
+  --> $DIR/deprecated.rs:8:9
    |
-LL | #[warn(clippy::regex_macro)]
-   |        ^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::if_let_redundant_pattern_matching)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/deprecated.rs:9:8
+error: lint `clippy::unsafe_vector_initialization` has been removed: the replacement suggested by this lint had substantially different behavior
+  --> $DIR/deprecated.rs:9:9
    |
-LL | #[warn(clippy::drop_bounds)]
-   |        ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
+LL | #![warn(clippy::unsafe_vector_initialization)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/deprecated.rs:10:8
+error: lint `clippy::unused_collect` has been removed: `collect` has been marked as #[must_use] in rustc and that covers all cases of this lint
+  --> $DIR/deprecated.rs:10:9
    |
-LL | #[warn(clippy::temporary_cstring_as_ptr)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
+LL | #![warn(clippy::unused_collect)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/deprecated.rs:11:8
+error: lint `clippy::replace_consts` has been removed: associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants
+  --> $DIR/deprecated.rs:11:9
    |
-LL | #[warn(clippy::panic_params)]
-   |        ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
+LL | #![warn(clippy::replace_consts)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/deprecated.rs:12:8
+error: lint `clippy::regex_macro` has been removed: the regex! macro has been removed from the regex crate in 2018
+  --> $DIR/deprecated.rs:12:9
    |
-LL | #[warn(clippy::unknown_clippy_lints)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
+LL | #![warn(clippy::regex_macro)]
+   |         ^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::find_map` has been removed: this lint has been replaced by `manual_find_map`, a more specific lint
-  --> $DIR/deprecated.rs:13:8
+  --> $DIR/deprecated.rs:13:9
    |
-LL | #[warn(clippy::find_map)]
-   |        ^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::find_map)]
+   |         ^^^^^^^^^^^^^^^^
 
 error: lint `clippy::filter_map` has been removed: this lint has been replaced by `manual_filter_map`, a more specific lint
-  --> $DIR/deprecated.rs:14:8
+  --> $DIR/deprecated.rs:14:9
    |
-LL | #[warn(clippy::filter_map)]
-   |        ^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::filter_map)]
+   |         ^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::pub_enum_variant_names` has been removed: set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items
-  --> $DIR/deprecated.rs:15:8
+  --> $DIR/deprecated.rs:15:9
    |
-LL | #[warn(clippy::pub_enum_variant_names)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::pub_enum_variant_names)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::wrong_pub_self_convention` has been removed: set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items
-  --> $DIR/deprecated.rs:16:8
-   |
-LL | #[warn(clippy::wrong_pub_self_convention)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/deprecated.rs:17:8
+  --> $DIR/deprecated.rs:16:9
    |
-LL | #[warn(clippy::invalid_atomic_ordering)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
+LL | #![warn(clippy::wrong_pub_self_convention)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 17 previous errors
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/diverging_sub_expression.rs b/src/tools/clippy/tests/ui/diverging_sub_expression.rs
index 4df241c9fc3..e27f9fea708 100644
--- a/src/tools/clippy/tests/ui/diverging_sub_expression.rs
+++ b/src/tools/clippy/tests/ui/diverging_sub_expression.rs
@@ -1,6 +1,5 @@
 #![warn(clippy::diverging_sub_expression)]
 #![allow(clippy::match_same_arms, clippy::logic_bug)]
-
 #[allow(clippy::empty_loop)]
 fn diverge() -> ! {
     loop {}
diff --git a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
index 170e7d92de4..c712a6a7e38 100644
--- a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
+++ b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
@@ -1,5 +1,5 @@
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:20:10
+  --> $DIR/diverging_sub_expression.rs:19:10
    |
 LL |     b || diverge();
    |          ^^^^^^^^^
@@ -7,34 +7,42 @@ LL |     b || diverge();
    = note: `-D clippy::diverging-sub-expression` implied by `-D warnings`
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:21:10
+  --> $DIR/diverging_sub_expression.rs:20:10
    |
 LL |     b || A.foo();
    |          ^^^^^^^
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:30:26
+  --> $DIR/diverging_sub_expression.rs:29:26
    |
 LL |             6 => true || return,
    |                          ^^^^^^
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:31:26
+  --> $DIR/diverging_sub_expression.rs:30:26
    |
 LL |             7 => true || continue,
    |                          ^^^^^^^^
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:34:26
+  --> $DIR/diverging_sub_expression.rs:33:26
    |
 LL |             3 => true || diverge(),
    |                          ^^^^^^^^^
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:39:26
+  --> $DIR/diverging_sub_expression.rs:36:30
+   |
+LL |                 _ => true || panic!("boo"),
+   |                              ^^^^^^^^^^^^^
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: sub-expression diverges
+  --> $DIR/diverging_sub_expression.rs:38:26
    |
 LL |             _ => true || break,
    |                          ^^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
new file mode 100644
index 00000000000..747801b40ee
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
@@ -0,0 +1,215 @@
+// run-rustfix
+//! This file tests for the `DOC_MARKDOWN` lint.
+
+#![allow(dead_code, incomplete_features)]
+#![warn(clippy::doc_markdown)]
+#![feature(custom_inner_attributes, generic_const_exprs, const_option)]
+#![rustfmt::skip]
+
+/// The `foo_bar` function does _nothing_. See also `foo::bar`. (note the dot there)
+/// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not `Foo::some_fun`
+/// which should be reported only once despite being __doubly bad__.
+/// Here be `::a::global:path`, and _`::another::global::path`_.  :: is not a path though.
+/// Import an item from `::awesome::global::blob::` (Intended postfix)
+/// These are the options for `::Cat`: (Intended trailing single colon, shouldn't be linted)
+/// That's not code ~`NotInCodeBlock`~.
+/// `be_sure_we_got_to_the_end_of_it`
+fn foo_bar() {
+}
+
+/// That one tests multiline ticks.
+/// ```rust
+/// foo_bar FOO_BAR
+/// _foo bar_
+/// ```
+///
+/// ~~~rust
+/// foo_bar FOO_BAR
+/// _foo bar_
+/// ~~~
+/// `be_sure_we_got_to_the_end_of_it`
+fn multiline_codeblock() {
+}
+
+/// This _is a test for
+/// multiline
+/// emphasis_.
+/// `be_sure_we_got_to_the_end_of_it`
+fn test_emphasis() {
+}
+
+/// This tests units. See also #835.
+/// kiB MiB GiB TiB PiB EiB
+/// kib Mib Gib Tib Pib Eib
+/// kB MB GB TB PB EB
+/// kb Mb Gb Tb Pb Eb
+/// 32kiB 32MiB 32GiB 32TiB 32PiB 32EiB
+/// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib
+/// 32kB 32MB 32GB 32TB 32PB 32EB
+/// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb
+/// NaN
+/// `be_sure_we_got_to_the_end_of_it`
+fn test_units() {
+}
+
+/// This tests allowed identifiers.
+/// KiB MiB GiB TiB PiB EiB
+/// DirectX
+/// ECMAScript
+/// GPLv2 GPLv3
+/// GitHub GitLab
+/// IPv4 IPv6
+/// ClojureScript CoffeeScript JavaScript PureScript TypeScript
+/// NaN NaNs
+/// OAuth GraphQL
+/// OCaml
+/// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS
+/// WebGL
+/// TensorFlow
+/// TrueType
+/// iOS macOS FreeBSD
+/// TeX LaTeX BibTeX BibLaTeX
+/// MinGW
+/// CamelCase (see also #2395)
+/// `be_sure_we_got_to_the_end_of_it`
+fn test_allowed() {
+}
+
+/// This test has [a `link_with_underscores`][chunked-example] inside it. See #823.
+/// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues)
+/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
+/// It can also be [`inline_link2`].
+///
+/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
+/// [inline_link]: https://foobar
+/// [inline_link2]: https://foobar
+/// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and
+/// `multiline_ticks` functions.
+///
+/// expression of the type  `_ <bit_op> m <cmp_op> c` (where `<bit_op>`
+/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` ,
+/// `be_sure_we_got_to_the_end_of_it`
+fn main() {
+    foo_bar();
+    multiline_codeblock();
+    test_emphasis();
+    test_units();
+}
+
+/// ## `CamelCaseThing`
+/// Talks about `CamelCaseThing`. Titles should be ignored; see issue #897.
+///
+/// # `CamelCaseThing`
+///
+/// Not a title #897 `CamelCaseThing`
+/// `be_sure_we_got_to_the_end_of_it`
+fn issue897() {
+}
+
+/// I am confused by brackets? (`x_y`)
+/// I am confused by brackets? (foo `x_y`)
+/// I am confused by brackets? (`x_y` foo)
+/// `be_sure_we_got_to_the_end_of_it`
+fn issue900() {
+}
+
+/// Diesel queries also have a similar problem to [Iterator][iterator], where
+/// /// More talking
+/// returning them from a function requires exposing the implementation of that
+/// function. The [`helper_types`][helper_types] module exists to help with this,
+/// but you might want to hide the return type or have it conditionally change.
+/// Boxing can achieve both.
+///
+/// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html
+/// [helper_types]: ../helper_types/index.html
+/// `be_sure_we_got_to_the_end_of_it`
+fn issue883() {
+}
+
+/// `foo_bar
+/// baz_quz`
+/// [foo
+/// bar](https://doc.rust-lang.org/stable/std/iter/trait.IteratorFooBar.html)
+fn multiline() {
+}
+
+/** E.g., serialization of an empty list: `FooBar`
+```
+That's in a code block: `PackedNode`
+```
+
+And `BarQuz` too.
+`be_sure_we_got_to_the_end_of_it`
+*/
+fn issue1073() {
+}
+
+/** E.g., serialization of an empty list: `FooBar`
+```
+That's in a code block: PackedNode
+```
+
+And `BarQuz` too.
+`be_sure_we_got_to_the_end_of_it`
+*/
+fn issue1073_alt() {
+}
+
+/// Tests more than three quotes:
+/// ````
+/// DoNotWarn
+/// ```
+/// StillDont
+/// ````
+/// `be_sure_we_got_to_the_end_of_it`
+fn four_quotes() {
+}
+
+#[cfg_attr(feature = "a", doc = " ```")]
+#[cfg_attr(not(feature = "a"), doc = " ```ignore")]
+/// fn main() {
+///     let s = "localhost:10000".to_string();
+///     println!("{}", s);
+/// }
+/// ```
+fn issue_1469() {}
+
+/**
+ * This is a doc comment that should not be a list
+ *This would also be an error under a strict common mark interpretation
+ */
+fn issue_1920() {}
+
+/// An iterator over `mycrate::Collection`'s values.
+/// It should not lint a `'static` lifetime in ticks.
+fn issue_2210() {}
+
+/// This should not cause the lint to trigger:
+/// #REQ-data-family.lint_partof_exists
+fn issue_2343() {}
+
+/// This should not cause an ICE:
+/// __|_ _|__||_|
+fn pulldown_cmark_crash() {}
+
+/// This should not lint
+/// (regression test for #7758)
+/// [plain text][path::to::item]
+fn intra_doc_link() {}
+
+// issue #7033 - generic_const_exprs ICE
+struct S<T, const N: usize>
+where [(); N.checked_next_power_of_two().unwrap()]: {
+    arr: [T; N.checked_next_power_of_two().unwrap()],
+    n: usize,
+}
+
+impl<T: Copy + Default, const N: usize> S<T, N>
+where [(); N.checked_next_power_of_two().unwrap()]: {
+    fn new() -> Self {
+        Self {
+            arr: [T::default(); N.checked_next_power_of_two().unwrap()],
+            n: 0,
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/doc/doc.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
index 342208e52b8..f3cf966157a 100644
--- a/src/tools/clippy/tests/ui/doc/doc.rs
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
@@ -1,3 +1,4 @@
+// run-rustfix
 //! This file tests for the `DOC_MARKDOWN` lint.
 
 #![allow(dead_code, incomplete_features)]
@@ -8,7 +9,9 @@
 /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
 /// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun
 /// which should be reported only once despite being __doubly bad__.
-/// Here be ::a::global:path.
+/// Here be ::a::global:path, and _::another::global::path_.  :: is not a path though.
+/// Import an item from ::awesome::global::blob:: (Intended postfix)
+/// These are the options for ::Cat: (Intended trailing single colon, shouldn't be linted)
 /// That's not code ~NotInCodeBlock~.
 /// be_sure_we_got_to_the_end_of_it
 fn foo_bar() {
@@ -162,12 +165,6 @@ fn issue1073_alt() {
 fn four_quotes() {
 }
 
-/// See [NIST SP 800-56A, revision 2].
-///
-/// [NIST SP 800-56A, revision 2]:
-///     https://github.com/rust-lang/rust-clippy/issues/902#issuecomment-261919419
-fn issue_902_comment() {}
-
 #[cfg_attr(feature = "a", doc = " ```")]
 #[cfg_attr(not(feature = "a"), doc = " ```ignore")]
 /// fn main() {
@@ -183,14 +180,6 @@ fn issue_1469() {}
  */
 fn issue_1920() {}
 
-/// Ok: <http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels>
-///
-/// Not ok: http://www.unicode.org
-/// Not ok: https://www.unicode.org
-/// Not ok: http://www.unicode.org/
-/// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
-fn issue_1832() {}
-
 /// An iterator over mycrate::Collection's values.
 /// It should not lint a `'static` lifetime in ticks.
 fn issue_2210() {}
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
new file mode 100644
index 00000000000..31132f86edb
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
@@ -0,0 +1,184 @@
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:9:9
+   |
+LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
+   |         ^^^^^^^ help: try: ``foo_bar``
+   |
+   = note: `-D clippy::doc-markdown` implied by `-D warnings`
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:9:51
+   |
+LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
+   |                                                   ^^^^^^^^ help: try: ``foo::bar``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:10:83
+   |
+LL | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun
+   |                                                                                   ^^^^^^^^^^^^^ help: try: ``Foo::some_fun``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:12:13
+   |
+LL | /// Here be ::a::global:path, and _::another::global::path_.  :: is not a path though.
+   |             ^^^^^^^^^^^^^^^^ help: try: ``::a::global:path``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:12:36
+   |
+LL | /// Here be ::a::global:path, and _::another::global::path_.  :: is not a path though.
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``::another::global::path``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:13:25
+   |
+LL | /// Import an item from ::awesome::global::blob:: (Intended postfix)
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``::awesome::global::blob::``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:14:31
+   |
+LL | /// These are the options for ::Cat: (Intended trailing single colon, shouldn't be linted)
+   |                               ^^^^^ help: try: ``::Cat``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:15:22
+   |
+LL | /// That's not code ~NotInCodeBlock~.
+   |                      ^^^^^^^^^^^^^^ help: try: ``NotInCodeBlock``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:16:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:30:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:37:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:51:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:74:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:78:22
+   |
+LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823.
+   |                      ^^^^^^^^^^^^^^^^^^^^^ help: try: ``link_with_underscores``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:81:21
+   |
+LL | /// It can also be [inline_link2].
+   |                     ^^^^^^^^^^^^ help: try: ``inline_link2``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:91:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:99:8
+   |
+LL | /// ## CamelCaseThing
+   |        ^^^^^^^^^^^^^^ help: try: ``CamelCaseThing``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:102:7
+   |
+LL | /// # CamelCaseThing
+   |       ^^^^^^^^^^^^^^ help: try: ``CamelCaseThing``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:104:22
+   |
+LL | /// Not a title #897 CamelCaseThing
+   |                      ^^^^^^^^^^^^^^ help: try: ``CamelCaseThing``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:105:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:112:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:125:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:136:43
+   |
+LL | /** E.g., serialization of an empty list: FooBar
+   |                                           ^^^^^^ help: try: ``FooBar``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:141:5
+   |
+LL | And BarQuz too.
+   |     ^^^^^^ help: try: ``BarQuz``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:142:1
+   |
+LL | be_sure_we_got_to_the_end_of_it
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:147:43
+   |
+LL | /** E.g., serialization of an empty list: FooBar
+   |                                           ^^^^^^ help: try: ``FooBar``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:152:5
+   |
+LL | And BarQuz too.
+   |     ^^^^^^ help: try: ``BarQuz``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:153:1
+   |
+LL | be_sure_we_got_to_the_end_of_it
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:164:5
+   |
+LL | /// be_sure_we_got_to_the_end_of_it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+  --> $DIR/doc-fixable.rs:183:22
+   |
+LL | /// An iterator over mycrate::Collection's values.
+   |                      ^^^^^^^^^^^^^^^^^^^ help: try: ``mycrate::Collection``
+
+error: aborting due to 30 previous errors
+
diff --git a/src/tools/clippy/tests/ui/doc/doc.stderr b/src/tools/clippy/tests/ui/doc/doc.stderr
deleted file mode 100644
index 7eab8a85f09..00000000000
--- a/src/tools/clippy/tests/ui/doc/doc.stderr
+++ /dev/null
@@ -1,190 +0,0 @@
-error: you should put `foo_bar` between ticks in the documentation
-  --> $DIR/doc.rs:8:9
-   |
-LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
-   |         ^^^^^^^
-   |
-   = note: `-D clippy::doc-markdown` implied by `-D warnings`
-
-error: you should put `foo::bar` between ticks in the documentation
-  --> $DIR/doc.rs:8:51
-   |
-LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
-   |                                                   ^^^^^^^^
-
-error: you should put `Foo::some_fun` between ticks in the documentation
-  --> $DIR/doc.rs:9:83
-   |
-LL | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun
-   |                                                                                   ^^^^^^^^^^^^^
-
-error: you should put `a::global:path` between ticks in the documentation
-  --> $DIR/doc.rs:11:15
-   |
-LL | /// Here be ::a::global:path.
-   |               ^^^^^^^^^^^^^^
-
-error: you should put `NotInCodeBlock` between ticks in the documentation
-  --> $DIR/doc.rs:12:22
-   |
-LL | /// That's not code ~NotInCodeBlock~.
-   |                      ^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:13:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:27:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:34:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:48:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:71:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `link_with_underscores` between ticks in the documentation
-  --> $DIR/doc.rs:75:22
-   |
-LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823.
-   |                      ^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `inline_link2` between ticks in the documentation
-  --> $DIR/doc.rs:78:21
-   |
-LL | /// It can also be [inline_link2].
-   |                     ^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:88:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `CamelCaseThing` between ticks in the documentation
-  --> $DIR/doc.rs:96:8
-   |
-LL | /// ## CamelCaseThing
-   |        ^^^^^^^^^^^^^^
-
-error: you should put `CamelCaseThing` between ticks in the documentation
-  --> $DIR/doc.rs:99:7
-   |
-LL | /// # CamelCaseThing
-   |       ^^^^^^^^^^^^^^
-
-error: you should put `CamelCaseThing` between ticks in the documentation
-  --> $DIR/doc.rs:101:22
-   |
-LL | /// Not a title #897 CamelCaseThing
-   |                      ^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:102:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:109:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:122:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `FooBar` between ticks in the documentation
-  --> $DIR/doc.rs:133:43
-   |
-LL | /** E.g., serialization of an empty list: FooBar
-   |                                           ^^^^^^
-
-error: you should put `BarQuz` between ticks in the documentation
-  --> $DIR/doc.rs:138:5
-   |
-LL | And BarQuz too.
-   |     ^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:139:1
-   |
-LL | be_sure_we_got_to_the_end_of_it
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `FooBar` between ticks in the documentation
-  --> $DIR/doc.rs:144:43
-   |
-LL | /** E.g., serialization of an empty list: FooBar
-   |                                           ^^^^^^
-
-error: you should put `BarQuz` between ticks in the documentation
-  --> $DIR/doc.rs:149:5
-   |
-LL | And BarQuz too.
-   |     ^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:150:1
-   |
-LL | be_sure_we_got_to_the_end_of_it
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
-  --> $DIR/doc.rs:161:5
-   |
-LL | /// be_sure_we_got_to_the_end_of_it
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
-  --> $DIR/doc.rs:188:13
-   |
-LL | /// Not ok: http://www.unicode.org
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
-  --> $DIR/doc.rs:189:13
-   |
-LL | /// Not ok: https://www.unicode.org
-   |             ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
-  --> $DIR/doc.rs:190:13
-   |
-LL | /// Not ok: http://www.unicode.org/
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
-  --> $DIR/doc.rs:191:13
-   |
-LL | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `mycrate::Collection` between ticks in the documentation
-  --> $DIR/doc.rs:194:22
-   |
-LL | /// An iterator over mycrate::Collection's values.
-   |                      ^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 31 previous errors
-
diff --git a/src/tools/clippy/tests/ui/doc/issue_1832.rs b/src/tools/clippy/tests/ui/doc/issue_1832.rs
new file mode 100644
index 00000000000..10586f16d46
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/issue_1832.rs
@@ -0,0 +1,9 @@
+/// Ok: <http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels>
+///
+/// Not ok: http://www.unicode.org
+/// Not ok: https://www.unicode.org
+/// Not ok: http://www.unicode.org/
+/// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
+fn issue_1832() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/doc/issue_902.rs b/src/tools/clippy/tests/ui/doc/issue_902.rs
new file mode 100644
index 00000000000..4b0c835dd3f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/issue_902.rs
@@ -0,0 +1,7 @@
+/// See [NIST SP 800-56A, revision 2].
+///
+/// [NIST SP 800-56A, revision 2]:
+///     https://github.com/rust-lang/rust-clippy/issues/902#issuecomment-261919419
+fn issue_902_comment() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr b/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr
index 45ca34e2a8c..9670e5c24fb 100644
--- a/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr
+++ b/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr
@@ -18,11 +18,11 @@ LL | /// This paragraph has `unbalanced_tick marks and should stop_linting.
    |
    = help: a backtick may be missing a pair
 
-error: you should put `should_be` between ticks in the documentation
+error: item in documentation is missing backticks
   --> $DIR/unbalanced_ticks.rs:15:32
    |
 LL | /// This paragraph is fine and should_be linted normally.
-   |                                ^^^^^^^^^
+   |                                ^^^^^^^^^ help: try: ``should_be``
 
 error: backticks are unbalanced
   --> $DIR/unbalanced_ticks.rs:17:1
@@ -32,11 +32,11 @@ LL | /// Double unbalanced backtick from ``here to here` should lint.
    |
    = help: a backtick may be missing a pair
 
-error: you should put `not_fine` between ticks in the documentation
+error: item in documentation is missing backticks
   --> $DIR/unbalanced_ticks.rs:30:8
    |
 LL | /// ## not_fine
-   |        ^^^^^^^^
+   |        ^^^^^^^^ help: try: ``not_fine``
 
 error: backticks are unbalanced
   --> $DIR/unbalanced_ticks.rs:32:1
@@ -54,11 +54,11 @@ LL | /// - This `item has unbalanced tick marks
    |
    = help: a backtick may be missing a pair
 
-error: you should put `backticks_here` between ticks in the documentation
+error: item in documentation is missing backticks
   --> $DIR/unbalanced_ticks.rs:35:23
    |
 LL | /// - This item needs backticks_here
-   |                       ^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^ help: try: ``backticks_here``
 
 error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/doc_errors.rs b/src/tools/clippy/tests/ui/doc_errors.rs
index c77a74a58f2..30fdd3b0873 100644
--- a/src/tools/clippy/tests/ui/doc_errors.rs
+++ b/src/tools/clippy/tests/ui/doc_errors.rs
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::missing_errors_doc)]
 #![allow(clippy::result_unit_err)]
 #![allow(clippy::unnecessary_wraps)]
diff --git a/src/tools/clippy/tests/ui/doc_errors.stderr b/src/tools/clippy/tests/ui/doc_errors.stderr
index b5a81419dae..c7b616e2897 100644
--- a/src/tools/clippy/tests/ui/doc_errors.stderr
+++ b/src/tools/clippy/tests/ui/doc_errors.stderr
@@ -1,5 +1,5 @@
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:8:1
+  --> $DIR/doc_errors.rs:7:1
    |
 LL | / pub fn pub_fn_missing_errors_header() -> Result<(), ()> {
 LL | |     unimplemented!();
@@ -9,7 +9,7 @@ LL | | }
    = note: `-D clippy::missing-errors-doc` implied by `-D warnings`
 
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:12:1
+  --> $DIR/doc_errors.rs:11:1
    |
 LL | / pub async fn async_pub_fn_missing_errors_header() -> Result<(), ()> {
 LL | |     unimplemented!();
@@ -17,7 +17,7 @@ LL | | }
    | |_^
 
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:17:1
+  --> $DIR/doc_errors.rs:16:1
    |
 LL | / pub fn pub_fn_returning_io_result() -> io::Result<()> {
 LL | |     unimplemented!();
@@ -25,7 +25,7 @@ LL | | }
    | |_^
 
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:22:1
+  --> $DIR/doc_errors.rs:21:1
    |
 LL | / pub async fn async_pub_fn_returning_io_result() -> io::Result<()> {
 LL | |     unimplemented!();
@@ -33,7 +33,7 @@ LL | | }
    | |_^
 
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:52:5
+  --> $DIR/doc_errors.rs:51:5
    |
 LL | /     pub fn pub_method_missing_errors_header() -> Result<(), ()> {
 LL | |         unimplemented!();
@@ -41,7 +41,7 @@ LL | |     }
    | |_____^
 
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:57:5
+  --> $DIR/doc_errors.rs:56:5
    |
 LL | /     pub async fn async_pub_method_missing_errors_header() -> Result<(), ()> {
 LL | |         unimplemented!();
@@ -49,7 +49,7 @@ LL | |     }
    | |_____^
 
 error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/doc_errors.rs:86:5
+  --> $DIR/doc_errors.rs:85:5
    |
 LL |     fn trait_method_missing_errors_header() -> Result<(), ()>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/doc_unsafe.rs b/src/tools/clippy/tests/ui/doc_unsafe.rs
index 03bb30f9083..4464a21b3b6 100644
--- a/src/tools/clippy/tests/ui/doc_unsafe.rs
+++ b/src/tools/clippy/tests/ui/doc_unsafe.rs
@@ -125,3 +125,8 @@ pub mod __macro {
         pub unsafe fn f() {}
     }
 }
+
+/// # Implementation safety
+pub unsafe trait DocumentedUnsafeTraitWithImplementationHeader {
+    fn method();
+}
diff --git a/src/tools/clippy/tests/ui/enum_variants.stderr b/src/tools/clippy/tests/ui/enum_variants.stderr
index 447fbb9e1bf..add8a91e26b 100644
--- a/src/tools/clippy/tests/ui/enum_variants.stderr
+++ b/src/tools/clippy/tests/ui/enum_variants.stderr
@@ -60,7 +60,7 @@ LL | | }
    |
    = help: remove the prefixes and use full paths to the variants instead of glob imports
 
-error: all variants have the same prefix: `With`
+error: all variants have the same prefix: `WithOut`
   --> $DIR/enum_variants.rs:81:1
    |
 LL | / enum Seallll {
diff --git a/src/tools/clippy/tests/ui/eval_order_dependence.rs b/src/tools/clippy/tests/ui/eval_order_dependence.rs
index 8e6a32b7be3..aad78319d48 100644
--- a/src/tools/clippy/tests/ui/eval_order_dependence.rs
+++ b/src/tools/clippy/tests/ui/eval_order_dependence.rs
@@ -1,5 +1,3 @@
-// edition:2018
-
 #[warn(clippy::eval_order_dependence)]
 #[allow(
     unused_assignments,
diff --git a/src/tools/clippy/tests/ui/eval_order_dependence.stderr b/src/tools/clippy/tests/ui/eval_order_dependence.stderr
index 4f611e308e1..7c6265a0879 100644
--- a/src/tools/clippy/tests/ui/eval_order_dependence.stderr
+++ b/src/tools/clippy/tests/ui/eval_order_dependence.stderr
@@ -1,48 +1,48 @@
 error: unsequenced read of `x`
-  --> $DIR/eval_order_dependence.rs:16:9
+  --> $DIR/eval_order_dependence.rs:14:9
    |
 LL |     } + x;
    |         ^
    |
    = note: `-D clippy::eval-order-dependence` implied by `-D warnings`
 note: whether read occurs before this write depends on evaluation order
-  --> $DIR/eval_order_dependence.rs:14:9
+  --> $DIR/eval_order_dependence.rs:12:9
    |
 LL |         x = 1;
    |         ^^^^^
 
 error: unsequenced read of `x`
-  --> $DIR/eval_order_dependence.rs:19:5
+  --> $DIR/eval_order_dependence.rs:17:5
    |
 LL |     x += {
    |     ^
    |
 note: whether read occurs before this write depends on evaluation order
-  --> $DIR/eval_order_dependence.rs:20:9
+  --> $DIR/eval_order_dependence.rs:18:9
    |
 LL |         x = 20;
    |         ^^^^^^
 
 error: unsequenced read of `x`
-  --> $DIR/eval_order_dependence.rs:32:12
+  --> $DIR/eval_order_dependence.rs:30:12
    |
 LL |         a: x,
    |            ^
    |
 note: whether read occurs before this write depends on evaluation order
-  --> $DIR/eval_order_dependence.rs:34:13
+  --> $DIR/eval_order_dependence.rs:32:13
    |
 LL |             x = 6;
    |             ^^^^^
 
 error: unsequenced read of `x`
-  --> $DIR/eval_order_dependence.rs:41:9
+  --> $DIR/eval_order_dependence.rs:39:9
    |
 LL |         x += {
    |         ^
    |
 note: whether read occurs before this write depends on evaluation order
-  --> $DIR/eval_order_dependence.rs:42:13
+  --> $DIR/eval_order_dependence.rs:40:13
    |
 LL |             x = 20;
    |             ^^^^^^
diff --git a/src/tools/clippy/tests/ui/fallible_impl_from.rs b/src/tools/clippy/tests/ui/fallible_impl_from.rs
index 495cd97e05e..5d5af4e4632 100644
--- a/src/tools/clippy/tests/ui/fallible_impl_from.rs
+++ b/src/tools/clippy/tests/ui/fallible_impl_from.rs
@@ -1,5 +1,4 @@
 #![deny(clippy::fallible_impl_from)]
-#![allow(clippy::if_then_panic)]
 
 // docs example
 struct Foo(i32);
diff --git a/src/tools/clippy/tests/ui/fallible_impl_from.stderr b/src/tools/clippy/tests/ui/fallible_impl_from.stderr
index f5d0b98c108..4e0f08a1215 100644
--- a/src/tools/clippy/tests/ui/fallible_impl_from.stderr
+++ b/src/tools/clippy/tests/ui/fallible_impl_from.stderr
@@ -1,5 +1,5 @@
 error: consider implementing `TryFrom` instead
-  --> $DIR/fallible_impl_from.rs:6:1
+  --> $DIR/fallible_impl_from.rs:5:1
    |
 LL | / impl From<String> for Foo {
 LL | |     fn from(s: String) -> Self {
@@ -15,13 +15,13 @@ LL | #![deny(clippy::fallible_impl_from)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
 note: potential failure(s)
-  --> $DIR/fallible_impl_from.rs:8:13
+  --> $DIR/fallible_impl_from.rs:7:13
    |
 LL |         Foo(s.parse().unwrap())
    |             ^^^^^^^^^^^^^^^^^^
 
 error: consider implementing `TryFrom` instead
-  --> $DIR/fallible_impl_from.rs:27:1
+  --> $DIR/fallible_impl_from.rs:26:1
    |
 LL | / impl From<usize> for Invalid {
 LL | |     fn from(i: usize) -> Invalid {
@@ -34,14 +34,14 @@ LL | | }
    |
    = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
 note: potential failure(s)
-  --> $DIR/fallible_impl_from.rs:30:13
+  --> $DIR/fallible_impl_from.rs:29:13
    |
 LL |             panic!();
    |             ^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: consider implementing `TryFrom` instead
-  --> $DIR/fallible_impl_from.rs:36:1
+  --> $DIR/fallible_impl_from.rs:35:1
    |
 LL | / impl From<Option<String>> for Invalid {
 LL | |     fn from(s: Option<String>) -> Invalid {
@@ -54,7 +54,7 @@ LL | | }
    |
    = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
 note: potential failure(s)
-  --> $DIR/fallible_impl_from.rs:38:17
+  --> $DIR/fallible_impl_from.rs:37:17
    |
 LL |         let s = s.unwrap();
    |                 ^^^^^^^^^^
@@ -65,10 +65,10 @@ LL |         } else if s.parse::<u32>().unwrap() != 42 {
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |             panic!("{:?}", s);
    |             ^^^^^^^^^^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: consider implementing `TryFrom` instead
-  --> $DIR/fallible_impl_from.rs:54:1
+  --> $DIR/fallible_impl_from.rs:53:1
    |
 LL | / impl<'a> From<&'a mut <Box<u32> as ProjStrTrait>::ProjString> for Invalid {
 LL | |     fn from(s: &'a mut <Box<u32> as ProjStrTrait>::ProjString) -> Invalid {
@@ -81,13 +81,13 @@ LL | | }
    |
    = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
 note: potential failure(s)
-  --> $DIR/fallible_impl_from.rs:56:12
+  --> $DIR/fallible_impl_from.rs:55:12
    |
 LL |         if s.parse::<u32>().ok().unwrap() != 42 {
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |             panic!("{:?}", s);
    |             ^^^^^^^^^^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/format.fixed b/src/tools/clippy/tests/ui/format.fixed
index 73fc750511c..64cb7b1cfb8 100644
--- a/src/tools/clippy/tests/ui/format.fixed
+++ b/src/tools/clippy/tests/ui/format.fixed
@@ -16,6 +16,8 @@ fn main() {
     r##"foo {}
 " bar"##.to_string();
 
+    let _ = String::new();
+
     "foo".to_string();
     format!("{:?}", "foo"); // Don't warn about `Debug`.
     format!("{:8}", "foo");
diff --git a/src/tools/clippy/tests/ui/format.rs b/src/tools/clippy/tests/ui/format.rs
index 2f4595650cb..a065b1b5683 100644
--- a/src/tools/clippy/tests/ui/format.rs
+++ b/src/tools/clippy/tests/ui/format.rs
@@ -18,6 +18,8 @@ fn main() {
 " bar"##
     );
 
+    let _ = format!("");
+
     format!("{}", "foo");
     format!("{:?}", "foo"); // Don't warn about `Debug`.
     format!("{:8}", "foo");
diff --git a/src/tools/clippy/tests/ui/format.stderr b/src/tools/clippy/tests/ui/format.stderr
index 701399b32d6..58ad7499bb2 100644
--- a/src/tools/clippy/tests/ui/format.stderr
+++ b/src/tools/clippy/tests/ui/format.stderr
@@ -34,64 +34,70 @@ LL ~ " bar"##.to_string();
    |
 
 error: useless use of `format!`
-  --> $DIR/format.rs:21:5
+  --> $DIR/format.rs:21:13
+   |
+LL |     let _ = format!("");
+   |             ^^^^^^^^^^^ help: consider using `String::new()`: `String::new()`
+
+error: useless use of `format!`
+  --> $DIR/format.rs:23:5
    |
 LL |     format!("{}", "foo");
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:25:5
+  --> $DIR/format.rs:27:5
    |
 LL |     format!("{:+}", "foo"); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:26:5
+  --> $DIR/format.rs:28:5
    |
 LL |     format!("{:<}", "foo"); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:31:5
+  --> $DIR/format.rs:33:5
    |
 LL |     format!("{}", arg);
    |     ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:35:5
+  --> $DIR/format.rs:37:5
    |
 LL |     format!("{:+}", arg); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:36:5
+  --> $DIR/format.rs:38:5
    |
 LL |     format!("{:<}", arg); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:63:5
+  --> $DIR/format.rs:65:5
    |
 LL |     format!("{}", 42.to_string());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:65:5
+  --> $DIR/format.rs:67:5
    |
 LL |     format!("{}", x.display().to_string());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:69:18
+  --> $DIR/format.rs:71:18
    |
 LL |     let _ = Some(format!("{}", a + "bar"));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:73:22
+  --> $DIR/format.rs:75:22
    |
 LL |     let _s: String = format!("{}", &*v.join("/n"));
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("/n")).to_string()`
 
-error: aborting due to 14 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/format_args.fixed b/src/tools/clippy/tests/ui/format_args.fixed
index 8376566c4d6..69b5e1c722e 100644
--- a/src/tools/clippy/tests/ui/format_args.fixed
+++ b/src/tools/clippy/tests/ui/format_args.fixed
@@ -5,6 +5,7 @@
 #![allow(unused_variables)]
 #![allow(clippy::assertions_on_constants)]
 #![allow(clippy::eq_op)]
+#![allow(clippy::print_literal)]
 #![warn(clippy::to_string_in_format_args)]
 
 use std::io::{stdout, Write};
@@ -97,9 +98,20 @@ fn main() {
     println!("{}", Z(1));
     println!("{}", **x);
     println!("{}", ***x_ref);
+    // https://github.com/rust-lang/rust-clippy/issues/7903
+    println!("{foo}{bar}", foo = "foo", bar = "bar");
+    println!("{foo}{bar}", foo = "foo", bar = "bar");
+    println!("{foo}{bar}", bar = "bar", foo = "foo");
+    println!("{foo}{bar}", bar = "bar", foo = "foo");
 
+    // negative tests
     println!("error: something failed at {}", Somewhere.to_string());
+    // The next two tests are negative because caching the string might be faster than calling `<X as
+    // Display>::fmt` twice.
     println!("{} and again {0}", x.to_string());
+    println!("{foo}{foo}", foo = "foo".to_string());
     my_macro!();
     println!("error: something failed at {}", my_other_macro!());
+    // https://github.com/rust-lang/rust-clippy/issues/7903
+    println!("{foo}{foo:?}", foo = "foo".to_string());
 }
diff --git a/src/tools/clippy/tests/ui/format_args.rs b/src/tools/clippy/tests/ui/format_args.rs
index 164cc07066d..3a434c5bf00 100644
--- a/src/tools/clippy/tests/ui/format_args.rs
+++ b/src/tools/clippy/tests/ui/format_args.rs
@@ -5,6 +5,7 @@
 #![allow(unused_variables)]
 #![allow(clippy::assertions_on_constants)]
 #![allow(clippy::eq_op)]
+#![allow(clippy::print_literal)]
 #![warn(clippy::to_string_in_format_args)]
 
 use std::io::{stdout, Write};
@@ -97,9 +98,20 @@ fn main() {
     println!("{}", Z(1).to_string());
     println!("{}", x.to_string());
     println!("{}", x_ref.to_string());
+    // https://github.com/rust-lang/rust-clippy/issues/7903
+    println!("{foo}{bar}", foo = "foo".to_string(), bar = "bar");
+    println!("{foo}{bar}", foo = "foo", bar = "bar".to_string());
+    println!("{foo}{bar}", bar = "bar".to_string(), foo = "foo");
+    println!("{foo}{bar}", bar = "bar", foo = "foo".to_string());
 
+    // negative tests
     println!("error: something failed at {}", Somewhere.to_string());
+    // The next two tests are negative because caching the string might be faster than calling `<X as
+    // Display>::fmt` twice.
     println!("{} and again {0}", x.to_string());
+    println!("{foo}{foo}", foo = "foo".to_string());
     my_macro!();
     println!("error: something failed at {}", my_other_macro!());
+    // https://github.com/rust-lang/rust-clippy/issues/7903
+    println!("{foo}{foo:?}", foo = "foo".to_string());
 }
diff --git a/src/tools/clippy/tests/ui/format_args.stderr b/src/tools/clippy/tests/ui/format_args.stderr
index 9cfc97edeaf..c0cbca50795 100644
--- a/src/tools/clippy/tests/ui/format_args.stderr
+++ b/src/tools/clippy/tests/ui/format_args.stderr
@@ -1,5 +1,5 @@
 error: `to_string` applied to a type that implements `Display` in `format!` args
-  --> $DIR/format_args.rs:75:72
+  --> $DIR/format_args.rs:76:72
    |
 LL |     let _ = format!("error: something failed at {}", Location::caller().to_string());
    |                                                                        ^^^^^^^^^^^^ help: remove this
@@ -7,100 +7,124 @@ LL |     let _ = format!("error: something failed at {}", Location::caller().to_
    = note: `-D clippy::to-string-in-format-args` implied by `-D warnings`
 
 error: `to_string` applied to a type that implements `Display` in `write!` args
-  --> $DIR/format_args.rs:79:27
+  --> $DIR/format_args.rs:80:27
    |
 LL |         Location::caller().to_string()
    |                           ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `writeln!` args
-  --> $DIR/format_args.rs:84:27
+  --> $DIR/format_args.rs:85:27
    |
 LL |         Location::caller().to_string()
    |                           ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `print!` args
-  --> $DIR/format_args.rs:86:63
+  --> $DIR/format_args.rs:87:63
    |
 LL |     print!("error: something failed at {}", Location::caller().to_string());
    |                                                               ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `println!` args
-  --> $DIR/format_args.rs:87:65
+  --> $DIR/format_args.rs:88:65
    |
 LL |     println!("error: something failed at {}", Location::caller().to_string());
    |                                                                 ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `eprint!` args
-  --> $DIR/format_args.rs:88:64
+  --> $DIR/format_args.rs:89:64
    |
 LL |     eprint!("error: something failed at {}", Location::caller().to_string());
    |                                                                ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `eprintln!` args
-  --> $DIR/format_args.rs:89:66
+  --> $DIR/format_args.rs:90:66
    |
 LL |     eprintln!("error: something failed at {}", Location::caller().to_string());
    |                                                                  ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `format_args!` args
-  --> $DIR/format_args.rs:90:77
+  --> $DIR/format_args.rs:91:77
    |
 LL |     let _ = format_args!("error: something failed at {}", Location::caller().to_string());
    |                                                                             ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `assert!` args
-  --> $DIR/format_args.rs:91:70
+  --> $DIR/format_args.rs:92:70
    |
 LL |     assert!(true, "error: something failed at {}", Location::caller().to_string());
    |                                                                      ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `assert_eq!` args
-  --> $DIR/format_args.rs:92:73
+  --> $DIR/format_args.rs:93:73
    |
 LL |     assert_eq!(0, 0, "error: something failed at {}", Location::caller().to_string());
    |                                                                         ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `assert_ne!` args
-  --> $DIR/format_args.rs:93:73
+  --> $DIR/format_args.rs:94:73
    |
 LL |     assert_ne!(0, 0, "error: something failed at {}", Location::caller().to_string());
    |                                                                         ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `panic!` args
-  --> $DIR/format_args.rs:94:63
+  --> $DIR/format_args.rs:95:63
    |
 LL |     panic!("error: something failed at {}", Location::caller().to_string());
    |                                                               ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `println!` args
-  --> $DIR/format_args.rs:95:20
+  --> $DIR/format_args.rs:96:20
    |
 LL |     println!("{}", X(1).to_string());
    |                    ^^^^^^^^^^^^^^^^ help: use this: `*X(1)`
 
 error: `to_string` applied to a type that implements `Display` in `println!` args
-  --> $DIR/format_args.rs:96:20
+  --> $DIR/format_args.rs:97:20
    |
 LL |     println!("{}", Y(&X(1)).to_string());
    |                    ^^^^^^^^^^^^^^^^^^^^ help: use this: `***Y(&X(1))`
 
 error: `to_string` applied to a type that implements `Display` in `println!` args
-  --> $DIR/format_args.rs:97:24
+  --> $DIR/format_args.rs:98:24
    |
 LL |     println!("{}", Z(1).to_string());
    |                        ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `println!` args
-  --> $DIR/format_args.rs:98:20
+  --> $DIR/format_args.rs:99:20
    |
 LL |     println!("{}", x.to_string());
    |                    ^^^^^^^^^^^^^ help: use this: `**x`
 
 error: `to_string` applied to a type that implements `Display` in `println!` args
-  --> $DIR/format_args.rs:99:20
+  --> $DIR/format_args.rs:100:20
    |
 LL |     println!("{}", x_ref.to_string());
    |                    ^^^^^^^^^^^^^^^^^ help: use this: `***x_ref`
 
-error: aborting due to 17 previous errors
+error: `to_string` applied to a type that implements `Display` in `println!` args
+  --> $DIR/format_args.rs:102:39
+   |
+LL |     println!("{foo}{bar}", foo = "foo".to_string(), bar = "bar");
+   |                                       ^^^^^^^^^^^^ help: remove this
+
+error: `to_string` applied to a type that implements `Display` in `println!` args
+  --> $DIR/format_args.rs:103:52
+   |
+LL |     println!("{foo}{bar}", foo = "foo", bar = "bar".to_string());
+   |                                                    ^^^^^^^^^^^^ help: remove this
+
+error: `to_string` applied to a type that implements `Display` in `println!` args
+  --> $DIR/format_args.rs:104:39
+   |
+LL |     println!("{foo}{bar}", bar = "bar".to_string(), foo = "foo");
+   |                                       ^^^^^^^^^^^^ help: remove this
+
+error: `to_string` applied to a type that implements `Display` in `println!` args
+  --> $DIR/format_args.rs:105:52
+   |
+LL |     println!("{foo}{bar}", bar = "bar", foo = "foo".to_string());
+   |                                                    ^^^^^^^^^^^^ help: remove this
+
+error: aborting due to 21 previous errors
 
diff --git a/src/tools/clippy/tests/ui/format_args_unfixable.rs b/src/tools/clippy/tests/ui/format_args_unfixable.rs
index a8c06c2bde6..b24ddf7321e 100644
--- a/src/tools/clippy/tests/ui/format_args_unfixable.rs
+++ b/src/tools/clippy/tests/ui/format_args_unfixable.rs
@@ -51,6 +51,7 @@ fn main() {
     assert_ne!(0, 0, "error: {}", format!("something failed at {}", Location::caller()));
     panic!("error: {}", format!("something failed at {}", Location::caller()));
 
+    // negative tests
     println!("error: {}", format_args!("something failed at {}", Location::caller()));
     println!("error: {:>70}", format!("something failed at {}", Location::caller()));
     println!("error: {} {0}", format!("something failed at {}", Location::caller()));
diff --git a/src/tools/clippy/tests/ui/future_not_send.rs b/src/tools/clippy/tests/ui/future_not_send.rs
index d3a920de4b6..858036692d6 100644
--- a/src/tools/clippy/tests/ui/future_not_send.rs
+++ b/src/tools/clippy/tests/ui/future_not_send.rs
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::future_not_send)]
 
 use std::cell::Cell;
diff --git a/src/tools/clippy/tests/ui/future_not_send.stderr b/src/tools/clippy/tests/ui/future_not_send.stderr
index c734051ccf3..3cc05e2fdbe 100644
--- a/src/tools/clippy/tests/ui/future_not_send.stderr
+++ b/src/tools/clippy/tests/ui/future_not_send.stderr
@@ -1,12 +1,12 @@
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:8:62
+  --> $DIR/future_not_send.rs:7:62
    |
 LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                                                              ^^^^ future returned by `private_future` is not `Send`
    |
    = note: `-D clippy::future-not-send` implied by `-D warnings`
 note: future is not `Send` as this value is used across an await
-  --> $DIR/future_not_send.rs:9:5
+  --> $DIR/future_not_send.rs:8:5
    |
 LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                         -- has type `std::rc::Rc<[u8]>` which is not `Send`
@@ -16,7 +16,7 @@ LL | }
    | - `rc` is later dropped here
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 note: future is not `Send` as this value is used across an await
-  --> $DIR/future_not_send.rs:9:5
+  --> $DIR/future_not_send.rs:8:5
    |
 LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                                       ---- has type `&std::cell::Cell<usize>` which is not `Send`
@@ -27,13 +27,13 @@ LL | }
    = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:12:42
+  --> $DIR/future_not_send.rs:11:42
    |
 LL | pub async fn public_future(rc: Rc<[u8]>) {
    |                                          ^ future returned by `public_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
-  --> $DIR/future_not_send.rs:13:5
+  --> $DIR/future_not_send.rs:12:5
    |
 LL | pub async fn public_future(rc: Rc<[u8]>) {
    |                            -- has type `std::rc::Rc<[u8]>` which is not `Send`
@@ -44,45 +44,45 @@ LL | }
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:20:63
+  --> $DIR/future_not_send.rs:19:63
    |
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                                                               ^^^^ future returned by `private_future2` is not `Send`
    |
 note: captured value is not `Send`
-  --> $DIR/future_not_send.rs:20:26
+  --> $DIR/future_not_send.rs:19:26
    |
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                          ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
-  --> $DIR/future_not_send.rs:20:40
+  --> $DIR/future_not_send.rs:19:40
    |
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                                        ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync`
    = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:24:43
+  --> $DIR/future_not_send.rs:23:43
    |
 LL | pub async fn public_future2(rc: Rc<[u8]>) {}
    |                                           ^ future returned by `public_future2` is not `Send`
    |
 note: captured value is not `Send`
-  --> $DIR/future_not_send.rs:24:29
+  --> $DIR/future_not_send.rs:23:29
    |
 LL | pub async fn public_future2(rc: Rc<[u8]>) {}
    |                             ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:35:39
+  --> $DIR/future_not_send.rs:34:39
    |
 LL |     async fn private_future(&self) -> usize {
    |                                       ^^^^^ future returned by `private_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
-  --> $DIR/future_not_send.rs:36:9
+  --> $DIR/future_not_send.rs:35:9
    |
 LL |     async fn private_future(&self) -> usize {
    |                             ----- has type `&Dummy` which is not `Send`
@@ -94,13 +94,13 @@ LL |     }
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:40:39
+  --> $DIR/future_not_send.rs:39:39
    |
 LL |     pub async fn public_future(&self) {
    |                                       ^ future returned by `public_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
-  --> $DIR/future_not_send.rs:41:9
+  --> $DIR/future_not_send.rs:40:9
    |
 LL |     pub async fn public_future(&self) {
    |                                ----- has type `&Dummy` which is not `Send`
@@ -111,13 +111,13 @@ LL |     }
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:50:37
+  --> $DIR/future_not_send.rs:49:37
    |
 LL | async fn generic_future<T>(t: T) -> T
    |                                     ^ future returned by `generic_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
-  --> $DIR/future_not_send.rs:55:5
+  --> $DIR/future_not_send.rs:54:5
    |
 LL |     let rt = &t;
    |         -- has type `&T` which is not `Send`
@@ -129,13 +129,13 @@ LL | }
    = note: `T` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:66:34
+  --> $DIR/future_not_send.rs:65:34
    |
 LL | async fn unclear_future<T>(t: T) {}
    |                                  ^ future returned by `unclear_future` is not `Send`
    |
 note: captured value is not `Send`
-  --> $DIR/future_not_send.rs:66:28
+  --> $DIR/future_not_send.rs:65:28
    |
 LL | async fn unclear_future<T>(t: T) {}
    |                            ^ has type `T` which is not `Send`
diff --git a/src/tools/clippy/tests/ui/if_not_else.rs b/src/tools/clippy/tests/ui/if_not_else.rs
index dc3fb1ceac9..b7012b43d29 100644
--- a/src/tools/clippy/tests/ui/if_not_else.rs
+++ b/src/tools/clippy/tests/ui/if_not_else.rs
@@ -1,6 +1,9 @@
 #![warn(clippy::all)]
 #![warn(clippy::if_not_else)]
 
+fn foo() -> bool {
+    unimplemented!()
+}
 fn bla() -> bool {
     unimplemented!()
 }
@@ -16,4 +19,11 @@ fn main() {
     } else {
         println!("Bunny");
     }
+    if !foo() {
+        println!("Foo");
+    } else if !bla() {
+        println!("Bugs");
+    } else {
+        println!("Bunny");
+    }
 }
diff --git a/src/tools/clippy/tests/ui/if_not_else.stderr b/src/tools/clippy/tests/ui/if_not_else.stderr
index 53d1b86d02a..8c8cc44bb03 100644
--- a/src/tools/clippy/tests/ui/if_not_else.stderr
+++ b/src/tools/clippy/tests/ui/if_not_else.stderr
@@ -1,5 +1,5 @@
 error: unnecessary boolean `not` operation
-  --> $DIR/if_not_else.rs:9:5
+  --> $DIR/if_not_else.rs:12:5
    |
 LL | /     if !bla() {
 LL | |         println!("Bugs");
@@ -12,7 +12,7 @@ LL | |     }
    = help: remove the `!` and swap the blocks of the `if`/`else`
 
 error: unnecessary `!=` operation
-  --> $DIR/if_not_else.rs:14:5
+  --> $DIR/if_not_else.rs:17:5
    |
 LL | /     if 4 != 5 {
 LL | |         println!("Bugs");
diff --git a/src/tools/clippy/tests/ui/implicit_hasher.rs b/src/tools/clippy/tests/ui/implicit_hasher.rs
index aa69b097410..fd96ca3f466 100644
--- a/src/tools/clippy/tests/ui/implicit_hasher.rs
+++ b/src/tools/clippy/tests/ui/implicit_hasher.rs
@@ -1,4 +1,3 @@
-// edition:2018
 // aux-build:implicit_hasher_macros.rs
 #![deny(clippy::implicit_hasher)]
 #![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/implicit_hasher.stderr b/src/tools/clippy/tests/ui/implicit_hasher.stderr
index 3f5f56b923f..59b0fba2a4c 100644
--- a/src/tools/clippy/tests/ui/implicit_hasher.stderr
+++ b/src/tools/clippy/tests/ui/implicit_hasher.stderr
@@ -1,11 +1,11 @@
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:17:35
+  --> $DIR/implicit_hasher.rs:16:35
    |
 LL | impl<K: Hash + Eq, V> Foo<i8> for HashMap<K, V> {
    |                                   ^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/implicit_hasher.rs:3:9
+  --> $DIR/implicit_hasher.rs:2:9
    |
 LL | #![deny(clippy::implicit_hasher)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL |         (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:26:36
+  --> $DIR/implicit_hasher.rs:25:36
    |
 LL | impl<K: Hash + Eq, V> Foo<i8> for (HashMap<K, V>,) {
    |                                    ^^^^^^^^^^^^^
@@ -34,7 +34,7 @@ LL |         ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Defa
    |           ~~~~~~~~~~~~~~~~~~     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:31:19
+  --> $DIR/implicit_hasher.rs:30:19
    |
 LL | impl Foo<i16> for HashMap<String, String> {
    |                   ^^^^^^^^^^^^^^^^^^^^^^^
@@ -49,7 +49,7 @@ LL |         (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:48:32
+  --> $DIR/implicit_hasher.rs:47:32
    |
 LL | impl<T: Hash + Eq> Foo<i8> for HashSet<T> {
    |                                ^^^^^^^^^^
@@ -64,7 +64,7 @@ LL |         (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:53:19
+  --> $DIR/implicit_hasher.rs:52:19
    |
 LL | impl Foo<i16> for HashSet<String> {
    |                   ^^^^^^^^^^^^^^^
@@ -79,7 +79,7 @@ LL |         (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:70:23
+  --> $DIR/implicit_hasher.rs:69:23
    |
 LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
    |                       ^^^^^^^^^^^^^^^^^
@@ -90,7 +90,7 @@ LL | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32, S>, _s
    |           +++++++++++++++++++++++++++++            ~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:70:53
+  --> $DIR/implicit_hasher.rs:69:53
    |
 LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
    |                                                     ^^^^^^^^^^^^
@@ -101,7 +101,7 @@ LL | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32>, _set:
    |           +++++++++++++++++++++++++++++                                          ~~~~~~~~~~~~~~~
 
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:74:43
+  --> $DIR/implicit_hasher.rs:73:43
    |
 LL |         impl<K: Hash + Eq, V> Foo<u8> for HashMap<K, V> {
    |                                           ^^^^^^^^^^^^^
@@ -120,7 +120,7 @@ LL |                 (HashMap::default(), HashMap::with_capacity_and_hasher(10,
    |                  ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:82:33
+  --> $DIR/implicit_hasher.rs:81:33
    |
 LL |         pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
    |                                 ^^^^^^^^^^^^^^^^^
@@ -135,7 +135,7 @@ LL |         pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i
    |                     +++++++++++++++++++++++++++++            ~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:82:63
+  --> $DIR/implicit_hasher.rs:81:63
    |
 LL |         pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
    |                                                               ^^^^^^^^^^^^
@@ -150,7 +150,7 @@ LL |         pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i
    |                     +++++++++++++++++++++++++++++                                          ~~~~~~~~~~~~~~~
 
 error: parameter of type `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:101:35
+  --> $DIR/implicit_hasher.rs:100:35
    |
 LL | pub async fn election_vote(_data: HashMap<i32, i32>) {}
    |                                   ^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/implicit_return.fixed b/src/tools/clippy/tests/ui/implicit_return.fixed
index 7698b88a88c..a51f7bc6a29 100644
--- a/src/tools/clippy/tests/ui/implicit_return.fixed
+++ b/src/tools/clippy/tests/ui/implicit_return.fixed
@@ -1,4 +1,3 @@
-// edition:2018
 // run-rustfix
 
 #![warn(clippy::implicit_return)]
diff --git a/src/tools/clippy/tests/ui/implicit_return.rs b/src/tools/clippy/tests/ui/implicit_return.rs
index 45bbc2ec670..03f8ec49d51 100644
--- a/src/tools/clippy/tests/ui/implicit_return.rs
+++ b/src/tools/clippy/tests/ui/implicit_return.rs
@@ -1,4 +1,3 @@
-// edition:2018
 // run-rustfix
 
 #![warn(clippy::implicit_return)]
diff --git a/src/tools/clippy/tests/ui/implicit_return.stderr b/src/tools/clippy/tests/ui/implicit_return.stderr
index 5e078b15ce3..522bc3bf895 100644
--- a/src/tools/clippy/tests/ui/implicit_return.stderr
+++ b/src/tools/clippy/tests/ui/implicit_return.stderr
@@ -1,5 +1,5 @@
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:13:5
+  --> $DIR/implicit_return.rs:12:5
    |
 LL |     true
    |     ^^^^ help: add `return` as shown: `return true`
@@ -7,85 +7,85 @@ LL |     true
    = note: `-D clippy::implicit-return` implied by `-D warnings`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:17:15
+  --> $DIR/implicit_return.rs:16:15
    |
 LL |     if true { true } else { false }
    |               ^^^^ help: add `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:17:29
+  --> $DIR/implicit_return.rs:16:29
    |
 LL |     if true { true } else { false }
    |                             ^^^^^ help: add `return` as shown: `return false`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:23:17
+  --> $DIR/implicit_return.rs:22:17
    |
 LL |         true => false,
    |                 ^^^^^ help: add `return` as shown: `return false`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:24:20
+  --> $DIR/implicit_return.rs:23:20
    |
 LL |         false => { true },
    |                    ^^^^ help: add `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:37:9
+  --> $DIR/implicit_return.rs:36:9
    |
 LL |         break true;
    |         ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:44:13
+  --> $DIR/implicit_return.rs:43:13
    |
 LL |             break true;
    |             ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:52:13
+  --> $DIR/implicit_return.rs:51:13
    |
 LL |             break true;
    |             ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:70:18
+  --> $DIR/implicit_return.rs:69:18
    |
 LL |     let _ = || { true };
    |                  ^^^^ help: add `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:71:16
+  --> $DIR/implicit_return.rs:70:16
    |
 LL |     let _ = || true;
    |                ^^^^ help: add `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:79:5
+  --> $DIR/implicit_return.rs:78:5
    |
 LL |     format!("test {}", "test")
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `return` as shown: `return format!("test {}", "test")`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:88:5
+  --> $DIR/implicit_return.rs:87:5
    |
 LL |     m!(true, false)
    |     ^^^^^^^^^^^^^^^ help: add `return` as shown: `return m!(true, false)`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:94:13
+  --> $DIR/implicit_return.rs:93:13
    |
 LL |             break true;
    |             ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:99:17
+  --> $DIR/implicit_return.rs:98:17
    |
 LL |                 break 'outer false;
    |                 ^^^^^^^^^^^^^^^^^^ help: change `break` to `return` as shown: `return false`
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:114:5
+  --> $DIR/implicit_return.rs:113:5
    |
 LL | /     loop {
 LL | |         m!(true);
@@ -100,7 +100,7 @@ LL +     }
    |
 
 error: missing `return` statement
-  --> $DIR/implicit_return.rs:128:5
+  --> $DIR/implicit_return.rs:127:5
    |
 LL |     true
    |     ^^^^ help: add `return` as shown: `return true`
diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed
index d1025743790..eb66d1afddc 100644
--- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed
+++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::inconsistent_struct_constructor)]
 #![allow(clippy::redundant_field_names)]
 #![allow(clippy::unnecessary_operation)]
diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs
index b095aa64a21..5caadc7c620 100644
--- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs
+++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::inconsistent_struct_constructor)]
 #![allow(clippy::redundant_field_names)]
 #![allow(clippy::unnecessary_operation)]
diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr
index ef308dedb16..c90189e964f 100644
--- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr
+++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr
@@ -1,5 +1,5 @@
 error: struct constructor field order is inconsistent with struct definition field order
-  --> $DIR/inconsistent_struct_constructor.rs:34:9
+  --> $DIR/inconsistent_struct_constructor.rs:33:9
    |
 LL |         Foo { y, x, z };
    |         ^^^^^^^^^^^^^^^ help: try: `Foo { x, y, z }`
@@ -7,7 +7,7 @@ LL |         Foo { y, x, z };
    = note: `-D clippy::inconsistent-struct-constructor` implied by `-D warnings`
 
 error: struct constructor field order is inconsistent with struct definition field order
-  --> $DIR/inconsistent_struct_constructor.rs:56:9
+  --> $DIR/inconsistent_struct_constructor.rs:55:9
    |
 LL | /         Foo {
 LL | |             z,
diff --git a/src/tools/clippy/tests/ui/issue-7447.stderr b/src/tools/clippy/tests/ui/issue-7447.stderr
new file mode 100644
index 00000000000..463a48b24a3
--- /dev/null
+++ b/src/tools/clippy/tests/ui/issue-7447.stderr
@@ -0,0 +1,19 @@
+error: sub-expression diverges
+  --> $DIR/issue-7447.rs:23:15
+   |
+LL |     byte_view(panic!());
+   |               ^^^^^^^^
+   |
+   = note: `-D clippy::diverging-sub-expression` implied by `-D warnings`
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: sub-expression diverges
+  --> $DIR/issue-7447.rs:24:19
+   |
+LL |     group_entries(panic!());
+   |                   ^^^^^^^^
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/issue_4266.rs b/src/tools/clippy/tests/ui/issue_4266.rs
index cc699b79e43..d9d48189bd7 100644
--- a/src/tools/clippy/tests/ui/issue_4266.rs
+++ b/src/tools/clippy/tests/ui/issue_4266.rs
@@ -1,4 +1,3 @@
-// edition:2018
 #![allow(dead_code)]
 
 async fn sink1<'a>(_: &'a str) {} // lint
diff --git a/src/tools/clippy/tests/ui/issue_4266.stderr b/src/tools/clippy/tests/ui/issue_4266.stderr
index 0426508e622..20419457b47 100644
--- a/src/tools/clippy/tests/ui/issue_4266.stderr
+++ b/src/tools/clippy/tests/ui/issue_4266.stderr
@@ -1,5 +1,5 @@
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/issue_4266.rs:4:1
+  --> $DIR/issue_4266.rs:3:1
    |
 LL | async fn sink1<'a>(_: &'a str) {} // lint
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | async fn sink1<'a>(_: &'a str) {} // lint
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/issue_4266.rs:8:1
+  --> $DIR/issue_4266.rs:7:1
    |
 LL | async fn one_to_one<'a>(s: &'a str) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/len_without_is_empty.rs b/src/tools/clippy/tests/ui/len_without_is_empty.rs
index b9d66347c27..1e938e72b57 100644
--- a/src/tools/clippy/tests/ui/len_without_is_empty.rs
+++ b/src/tools/clippy/tests/ui/len_without_is_empty.rs
@@ -1,5 +1,3 @@
-// edition:2018
-
 #![warn(clippy::len_without_is_empty)]
 #![allow(dead_code, unused)]
 
diff --git a/src/tools/clippy/tests/ui/len_without_is_empty.stderr b/src/tools/clippy/tests/ui/len_without_is_empty.stderr
index 3282709bcd6..a1f48f7610b 100644
--- a/src/tools/clippy/tests/ui/len_without_is_empty.stderr
+++ b/src/tools/clippy/tests/ui/len_without_is_empty.stderr
@@ -1,5 +1,5 @@
 error: struct `PubOne` has a public `len` method, but no `is_empty` method
-  --> $DIR/len_without_is_empty.rs:9:5
+  --> $DIR/len_without_is_empty.rs:7:5
    |
 LL |     pub fn len(&self) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     pub fn len(&self) -> isize {
    = note: `-D clippy::len-without-is-empty` implied by `-D warnings`
 
 error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method
-  --> $DIR/len_without_is_empty.rs:57:1
+  --> $DIR/len_without_is_empty.rs:55:1
    |
 LL | / pub trait PubTraitsToo {
 LL | |     fn len(&self) -> isize;
@@ -15,45 +15,45 @@ LL | | }
    | |_^
 
 error: struct `HasIsEmpty` has a public `len` method, but a private `is_empty` method
-  --> $DIR/len_without_is_empty.rs:70:5
+  --> $DIR/len_without_is_empty.rs:68:5
    |
 LL |     pub fn len(&self) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `is_empty` defined here
-  --> $DIR/len_without_is_empty.rs:74:5
+  --> $DIR/len_without_is_empty.rs:72:5
    |
 LL |     fn is_empty(&self) -> bool {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: struct `HasWrongIsEmpty` has a public `len` method, but the `is_empty` method has an unexpected signature
-  --> $DIR/len_without_is_empty.rs:82:5
+  --> $DIR/len_without_is_empty.rs:80:5
    |
 LL |     pub fn len(&self) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `is_empty` defined here
-  --> $DIR/len_without_is_empty.rs:86:5
+  --> $DIR/len_without_is_empty.rs:84:5
    |
 LL |     pub fn is_empty(&self, x: u32) -> bool {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected signature: `(&self) -> bool`
 
 error: struct `MismatchedSelf` has a public `len` method, but the `is_empty` method has an unexpected signature
-  --> $DIR/len_without_is_empty.rs:94:5
+  --> $DIR/len_without_is_empty.rs:92:5
    |
 LL |     pub fn len(self) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `is_empty` defined here
-  --> $DIR/len_without_is_empty.rs:98:5
+  --> $DIR/len_without_is_empty.rs:96:5
    |
 LL |     pub fn is_empty(&self) -> bool {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected signature: `(self) -> bool`
 
 error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method
-  --> $DIR/len_without_is_empty.rs:173:1
+  --> $DIR/len_without_is_empty.rs:171:1
    |
 LL | / pub trait DependsOnFoo: Foo {
 LL | |     fn len(&mut self) -> usize;
@@ -61,33 +61,33 @@ LL | | }
    | |_^
 
 error: struct `OptionalLen3` has a public `len` method, but the `is_empty` method has an unexpected signature
-  --> $DIR/len_without_is_empty.rs:218:5
+  --> $DIR/len_without_is_empty.rs:216:5
    |
 LL |     pub fn len(&self) -> usize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `is_empty` defined here
-  --> $DIR/len_without_is_empty.rs:223:5
+  --> $DIR/len_without_is_empty.rs:221:5
    |
 LL |     pub fn is_empty(&self) -> Option<bool> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected signature: `(&self) -> bool`
 
 error: struct `ResultLen` has a public `len` method, but the `is_empty` method has an unexpected signature
-  --> $DIR/len_without_is_empty.rs:230:5
+  --> $DIR/len_without_is_empty.rs:228:5
    |
 LL |     pub fn len(&self) -> Result<usize, ()> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `is_empty` defined here
-  --> $DIR/len_without_is_empty.rs:235:5
+  --> $DIR/len_without_is_empty.rs:233:5
    |
 LL |     pub fn is_empty(&self) -> Option<bool> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected signature: `(&self) -> bool` or `(&self) -> Result<bool>
 
 error: this returns a `Result<_, ()>`
-  --> $DIR/len_without_is_empty.rs:230:5
+  --> $DIR/len_without_is_empty.rs:228:5
    |
 LL |     pub fn len(&self) -> Result<usize, ()> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -96,7 +96,7 @@ LL |     pub fn len(&self) -> Result<usize, ()> {
    = help: use a custom `Error` type instead
 
 error: this returns a `Result<_, ()>`
-  --> $DIR/len_without_is_empty.rs:242:5
+  --> $DIR/len_without_is_empty.rs:240:5
    |
 LL |     pub fn len(&self) -> Result<usize, ()> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -104,7 +104,7 @@ LL |     pub fn len(&self) -> Result<usize, ()> {
    = help: use a custom `Error` type instead
 
 error: this returns a `Result<_, ()>`
-  --> $DIR/len_without_is_empty.rs:246:5
+  --> $DIR/len_without_is_empty.rs:244:5
    |
 LL |     pub fn is_empty(&self) -> Result<bool, ()> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -112,7 +112,7 @@ LL |     pub fn is_empty(&self) -> Result<bool, ()> {
    = help: use a custom `Error` type instead
 
 error: this returns a `Result<_, ()>`
-  --> $DIR/len_without_is_empty.rs:253:5
+  --> $DIR/len_without_is_empty.rs:251:5
    |
 LL |     pub fn len(&self) -> Result<usize, ()> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/literals.rs b/src/tools/clippy/tests/ui/literals.rs
index a72a74b9131..e60ce8492fc 100644
--- a/src/tools/clippy/tests/ui/literals.rs
+++ b/src/tools/clippy/tests/ui/literals.rs
@@ -2,7 +2,8 @@
 
 #![warn(clippy::mixed_case_hex_literals)]
 #![warn(clippy::zero_prefixed_literal)]
-#![allow(clippy::unseparated_literal_suffix)]
+#![warn(clippy::unseparated_literal_suffix)]
+#![warn(clippy::separated_literal_suffix)]
 #![allow(dead_code)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/literals.stderr b/src/tools/clippy/tests/ui/literals.stderr
index 99542e20f78..365b2407473 100644
--- a/src/tools/clippy/tests/ui/literals.stderr
+++ b/src/tools/clippy/tests/ui/literals.stderr
@@ -1,25 +1,65 @@
+error: integer type suffix should not be separated by an underscore
+  --> $DIR/literals.rs:12:15
+   |
+LL |     let ok4 = 0xab_cd_i32;
+   |               ^^^^^^^^^^^ help: remove the underscore: `0xab_cdi32`
+   |
+   = note: `-D clippy::separated-literal-suffix` implied by `-D warnings`
+
+error: integer type suffix should not be separated by an underscore
+  --> $DIR/literals.rs:13:15
+   |
+LL |     let ok5 = 0xAB_CD_u32;
+   |               ^^^^^^^^^^^ help: remove the underscore: `0xAB_CDu32`
+
+error: integer type suffix should not be separated by an underscore
+  --> $DIR/literals.rs:14:15
+   |
+LL |     let ok5 = 0xAB_CD_isize;
+   |               ^^^^^^^^^^^^^ help: remove the underscore: `0xAB_CDisize`
+
 error: inconsistent casing in hexadecimal literal
-  --> $DIR/literals.rs:14:17
+  --> $DIR/literals.rs:15:17
    |
 LL |     let fail1 = 0xabCD;
    |                 ^^^^^^
    |
    = note: `-D clippy::mixed-case-hex-literals` implied by `-D warnings`
 
+error: integer type suffix should not be separated by an underscore
+  --> $DIR/literals.rs:16:17
+   |
+LL |     let fail2 = 0xabCD_u32;
+   |                 ^^^^^^^^^^ help: remove the underscore: `0xabCDu32`
+
 error: inconsistent casing in hexadecimal literal
-  --> $DIR/literals.rs:15:17
+  --> $DIR/literals.rs:16:17
    |
 LL |     let fail2 = 0xabCD_u32;
    |                 ^^^^^^^^^^
 
+error: integer type suffix should not be separated by an underscore
+  --> $DIR/literals.rs:17:17
+   |
+LL |     let fail2 = 0xabCD_isize;
+   |                 ^^^^^^^^^^^^ help: remove the underscore: `0xabCDisize`
+
 error: inconsistent casing in hexadecimal literal
-  --> $DIR/literals.rs:16:17
+  --> $DIR/literals.rs:17:17
    |
 LL |     let fail2 = 0xabCD_isize;
    |                 ^^^^^^^^^^^^
 
+error: integer type suffix should be separated by an underscore
+  --> $DIR/literals.rs:18:27
+   |
+LL |     let fail_multi_zero = 000_123usize;
+   |                           ^^^^^^^^^^^^ help: add an underscore: `000_123_usize`
+   |
+   = note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings`
+
 error: this is a decimal constant
-  --> $DIR/literals.rs:17:27
+  --> $DIR/literals.rs:18:27
    |
 LL |     let fail_multi_zero = 000_123usize;
    |                           ^^^^^^^^^^^^
@@ -34,8 +74,14 @@ help: if you mean to use an octal constant, use `0o`
 LL |     let fail_multi_zero = 0o123usize;
    |                           ~~~~~~~~~~
 
+error: integer type suffix should not be separated by an underscore
+  --> $DIR/literals.rs:21:16
+   |
+LL |     let ok10 = 0_i64;
+   |                ^^^^^ help: remove the underscore: `0i64`
+
 error: this is a decimal constant
-  --> $DIR/literals.rs:21:17
+  --> $DIR/literals.rs:22:17
    |
 LL |     let fail8 = 0123;
    |                 ^^^^
@@ -49,8 +95,14 @@ help: if you mean to use an octal constant, use `0o`
 LL |     let fail8 = 0o123;
    |                 ~~~~~
 
+error: integer type suffix should not be separated by an underscore
+  --> $DIR/literals.rs:31:16
+   |
+LL |     let ok17 = 0x123_4567_8901_usize;
+   |                ^^^^^^^^^^^^^^^^^^^^^ help: remove the underscore: `0x123_4567_8901usize`
+
 error: digits grouped inconsistently by underscores
-  --> $DIR/literals.rs:33:18
+  --> $DIR/literals.rs:34:18
    |
 LL |     let fail19 = 12_3456_21;
    |                  ^^^^^^^^^^ help: consider: `12_345_621`
@@ -58,19 +110,19 @@ LL |     let fail19 = 12_3456_21;
    = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings`
 
 error: digits grouped inconsistently by underscores
-  --> $DIR/literals.rs:34:18
+  --> $DIR/literals.rs:35:18
    |
 LL |     let fail22 = 3__4___23;
    |                  ^^^^^^^^^ help: consider: `3_423`
 
 error: digits grouped inconsistently by underscores
-  --> $DIR/literals.rs:35:18
+  --> $DIR/literals.rs:36:18
    |
 LL |     let fail23 = 3__16___23;
    |                  ^^^^^^^^^^ help: consider: `31_623`
 
 error: digits of hex or binary literal not grouped by four
-  --> $DIR/literals.rs:37:18
+  --> $DIR/literals.rs:38:18
    |
 LL |     let fail24 = 0xAB_ABC_AB;
    |                  ^^^^^^^^^^^ help: consider: `0x0ABA_BCAB`
@@ -78,10 +130,10 @@ LL |     let fail24 = 0xAB_ABC_AB;
    = note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
 
 error: digits of hex or binary literal not grouped by four
-  --> $DIR/literals.rs:38:18
+  --> $DIR/literals.rs:39:18
    |
 LL |     let fail25 = 0b01_100_101;
    |                  ^^^^^^^^^^^^ help: consider: `0b0110_0101`
 
-error: aborting due to 10 previous errors
+error: aborting due to 18 previous errors
 
diff --git a/src/tools/clippy/tests/ui/macro_use_imports.fixed b/src/tools/clippy/tests/ui/macro_use_imports.fixed
index 70d49d9f2c4..9171558f3a2 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports.fixed
+++ b/src/tools/clippy/tests/ui/macro_use_imports.fixed
@@ -1,4 +1,3 @@
-// compile-flags: --edition 2018
 // aux-build:macro_rules.rs
 // aux-build:macro_use_helper.rs
 // aux-build:proc_macro_derive.rs
diff --git a/src/tools/clippy/tests/ui/macro_use_imports.rs b/src/tools/clippy/tests/ui/macro_use_imports.rs
index 68370023861..cd01fd43f6d 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports.rs
+++ b/src/tools/clippy/tests/ui/macro_use_imports.rs
@@ -1,4 +1,3 @@
-// compile-flags: --edition 2018
 // aux-build:macro_rules.rs
 // aux-build:macro_use_helper.rs
 // aux-build:proc_macro_derive.rs
diff --git a/src/tools/clippy/tests/ui/macro_use_imports.stderr b/src/tools/clippy/tests/ui/macro_use_imports.stderr
index 49314b7506d..f8c86c8d917 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports.stderr
+++ b/src/tools/clippy/tests/ui/macro_use_imports.stderr
@@ -1,5 +1,5 @@
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:19:5
+  --> $DIR/macro_use_imports.rs:18:5
    |
 LL |     #[macro_use]
    |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};`
@@ -7,22 +7,22 @@ LL |     #[macro_use]
    = note: `-D clippy::macro-use-imports` implied by `-D warnings`
 
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:25:5
+  --> $DIR/macro_use_imports.rs:20:5
    |
 LL |     #[macro_use]
-   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;`
+   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;`
 
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:21:5
+  --> $DIR/macro_use_imports.rs:22:5
    |
 LL |     #[macro_use]
-   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;`
+   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};`
 
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:23:5
+  --> $DIR/macro_use_imports.rs:24:5
    |
 LL |     #[macro_use]
-   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};`
+   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/if_then_panic.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
index 0998f8ffa9d..11fe06c5724 100644
--- a/src/tools/clippy/tests/ui/if_then_panic.fixed
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
@@ -1,5 +1,8 @@
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
 // run-rustfix
-#![warn(clippy::if_then_panic)]
+#![warn(clippy::manual_assert)]
 
 fn main() {
     let a = vec![1, 2, 3];
diff --git a/src/tools/clippy/tests/ui/if_then_panic.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
index 5bb62f87566..03c03472f90 100644
--- a/src/tools/clippy/tests/ui/if_then_panic.stderr
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
@@ -1,15 +1,15 @@
 error: only a `panic!` in `if`-then statement
-  --> $DIR/if_then_panic.rs:19:5
+  --> $DIR/manual_assert.rs:22:5
    |
 LL | /     if !a.is_empty() {
 LL | |         panic!("qaqaq{:?}", a);
 LL | |     }
    | |_____^ help: try: `assert!(a.is_empty(), "qaqaq{:?}", a);`
    |
-   = note: `-D clippy::if-then-panic` implied by `-D warnings`
+   = note: `-D clippy::manual-assert` implied by `-D warnings`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/if_then_panic.rs:22:5
+  --> $DIR/manual_assert.rs:25:5
    |
 LL | /     if !a.is_empty() {
 LL | |         panic!("qwqwq");
@@ -17,7 +17,7 @@ LL | |     }
    | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/if_then_panic.rs:39:5
+  --> $DIR/manual_assert.rs:42:5
    |
 LL | /     if b.is_empty() {
 LL | |         panic!("panic1");
@@ -25,7 +25,7 @@ LL | |     }
    | |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/if_then_panic.rs:42:5
+  --> $DIR/manual_assert.rs:45:5
    |
 LL | /     if b.is_empty() && a.is_empty() {
 LL | |         panic!("panic2");
@@ -33,7 +33,7 @@ LL | |     }
    | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/if_then_panic.rs:45:5
+  --> $DIR/manual_assert.rs:48:5
    |
 LL | /     if a.is_empty() && !b.is_empty() {
 LL | |         panic!("panic3");
@@ -41,7 +41,7 @@ LL | |     }
    | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/if_then_panic.rs:48:5
+  --> $DIR/manual_assert.rs:51:5
    |
 LL | /     if b.is_empty() || a.is_empty() {
 LL | |         panic!("panic4");
@@ -49,7 +49,7 @@ LL | |     }
    | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/if_then_panic.rs:51:5
+  --> $DIR/manual_assert.rs:54:5
    |
 LL | /     if a.is_empty() || !b.is_empty() {
 LL | |         panic!("panic5");
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
new file mode 100644
index 00000000000..11fe06c5724
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
@@ -0,0 +1,43 @@
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
+// run-rustfix
+#![warn(clippy::manual_assert)]
+
+fn main() {
+    let a = vec![1, 2, 3];
+    let c = Some(2);
+    if !a.is_empty()
+        && a.len() == 3
+        && c != None
+        && !a.is_empty()
+        && a.len() == 3
+        && !a.is_empty()
+        && a.len() == 3
+        && !a.is_empty()
+        && a.len() == 3
+    {
+        panic!("qaqaq{:?}", a);
+    }
+    assert!(a.is_empty(), "qaqaq{:?}", a);
+    assert!(a.is_empty(), "qwqwq");
+    if a.len() == 3 {
+        println!("qwq");
+        println!("qwq");
+        println!("qwq");
+    }
+    if let Some(b) = c {
+        panic!("orz {}", b);
+    }
+    if a.len() == 3 {
+        panic!("qaqaq");
+    } else {
+        println!("qwq");
+    }
+    let b = vec![1, 2, 3];
+    assert!(!b.is_empty(), "panic1");
+    assert!(!(b.is_empty() && a.is_empty()), "panic2");
+    assert!(!(a.is_empty() && !b.is_empty()), "panic3");
+    assert!(!(b.is_empty() || a.is_empty()), "panic4");
+    assert!(!(a.is_empty() || !b.is_empty()), "panic5");
+}
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
new file mode 100644
index 00000000000..03c03472f90
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
@@ -0,0 +1,60 @@
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:22:5
+   |
+LL | /     if !a.is_empty() {
+LL | |         panic!("qaqaq{:?}", a);
+LL | |     }
+   | |_____^ help: try: `assert!(a.is_empty(), "qaqaq{:?}", a);`
+   |
+   = note: `-D clippy::manual-assert` implied by `-D warnings`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:25:5
+   |
+LL | /     if !a.is_empty() {
+LL | |         panic!("qwqwq");
+LL | |     }
+   | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:42:5
+   |
+LL | /     if b.is_empty() {
+LL | |         panic!("panic1");
+LL | |     }
+   | |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:45:5
+   |
+LL | /     if b.is_empty() && a.is_empty() {
+LL | |         panic!("panic2");
+LL | |     }
+   | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:48:5
+   |
+LL | /     if a.is_empty() && !b.is_empty() {
+LL | |         panic!("panic3");
+LL | |     }
+   | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:51:5
+   |
+LL | /     if b.is_empty() || a.is_empty() {
+LL | |         panic!("panic4");
+LL | |     }
+   | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:54:5
+   |
+LL | /     if a.is_empty() || !b.is_empty() {
+LL | |         panic!("panic5");
+LL | |     }
+   | |_____^ help: try: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_assert.fixed b/src/tools/clippy/tests/ui/manual_assert.fixed
new file mode 100644
index 00000000000..11fe06c5724
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_assert.fixed
@@ -0,0 +1,43 @@
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
+// run-rustfix
+#![warn(clippy::manual_assert)]
+
+fn main() {
+    let a = vec![1, 2, 3];
+    let c = Some(2);
+    if !a.is_empty()
+        && a.len() == 3
+        && c != None
+        && !a.is_empty()
+        && a.len() == 3
+        && !a.is_empty()
+        && a.len() == 3
+        && !a.is_empty()
+        && a.len() == 3
+    {
+        panic!("qaqaq{:?}", a);
+    }
+    assert!(a.is_empty(), "qaqaq{:?}", a);
+    assert!(a.is_empty(), "qwqwq");
+    if a.len() == 3 {
+        println!("qwq");
+        println!("qwq");
+        println!("qwq");
+    }
+    if let Some(b) = c {
+        panic!("orz {}", b);
+    }
+    if a.len() == 3 {
+        panic!("qaqaq");
+    } else {
+        println!("qwq");
+    }
+    let b = vec![1, 2, 3];
+    assert!(!b.is_empty(), "panic1");
+    assert!(!(b.is_empty() && a.is_empty()), "panic2");
+    assert!(!(a.is_empty() && !b.is_empty()), "panic3");
+    assert!(!(b.is_empty() || a.is_empty()), "panic4");
+    assert!(!(a.is_empty() || !b.is_empty()), "panic5");
+}
diff --git a/src/tools/clippy/tests/ui/if_then_panic.rs b/src/tools/clippy/tests/ui/manual_assert.rs
index 10433c8d54f..8713426fc88 100644
--- a/src/tools/clippy/tests/ui/if_then_panic.rs
+++ b/src/tools/clippy/tests/ui/manual_assert.rs
@@ -1,5 +1,8 @@
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
 // run-rustfix
-#![warn(clippy::if_then_panic)]
+#![warn(clippy::manual_assert)]
 
 fn main() {
     let a = vec![1, 2, 3];
diff --git a/src/tools/clippy/tests/ui/manual_async_fn.fixed b/src/tools/clippy/tests/ui/manual_async_fn.fixed
index 5184f6fdb88..136cc96be70 100644
--- a/src/tools/clippy/tests/ui/manual_async_fn.fixed
+++ b/src/tools/clippy/tests/ui/manual_async_fn.fixed
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::manual_async_fn)]
 #![allow(unused)]
 
diff --git a/src/tools/clippy/tests/ui/manual_async_fn.rs b/src/tools/clippy/tests/ui/manual_async_fn.rs
index 68c0e591f0b..ddc453ffdb7 100644
--- a/src/tools/clippy/tests/ui/manual_async_fn.rs
+++ b/src/tools/clippy/tests/ui/manual_async_fn.rs
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::manual_async_fn)]
 #![allow(unused)]
 
diff --git a/src/tools/clippy/tests/ui/manual_async_fn.stderr b/src/tools/clippy/tests/ui/manual_async_fn.stderr
index 51f1a52b6dd..7435f46074c 100644
--- a/src/tools/clippy/tests/ui/manual_async_fn.stderr
+++ b/src/tools/clippy/tests/ui/manual_async_fn.stderr
@@ -1,5 +1,5 @@
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:8:1
+  --> $DIR/manual_async_fn.rs:7:1
    |
 LL | fn fut() -> impl Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -15,7 +15,7 @@ LL | fn fut() -> impl Future<Output = i32> { 42 }
    |                                       ~~~~~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:13:1
+  --> $DIR/manual_async_fn.rs:12:1
    |
 LL | fn fut2() ->impl Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -30,7 +30,7 @@ LL | fn fut2() ->impl Future<Output = i32> { 42 }
    |                                       ~~~~~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:18:1
+  --> $DIR/manual_async_fn.rs:17:1
    |
 LL | fn fut3()-> impl Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -45,7 +45,7 @@ LL | fn fut3()-> impl Future<Output = i32> { 42 }
    |                                       ~~~~~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:22:1
+  --> $DIR/manual_async_fn.rs:21:1
    |
 LL | fn empty_fut() -> impl Future<Output = ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -60,7 +60,7 @@ LL | fn empty_fut() -> impl Future<Output = ()> {}
    |                                            ~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:27:1
+  --> $DIR/manual_async_fn.rs:26:1
    |
 LL | fn empty_fut2() ->impl Future<Output = ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -75,7 +75,7 @@ LL | fn empty_fut2() ->impl Future<Output = ()> {}
    |                                            ~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:32:1
+  --> $DIR/manual_async_fn.rs:31:1
    |
 LL | fn empty_fut3()-> impl Future<Output = ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -90,7 +90,7 @@ LL | fn empty_fut3()-> impl Future<Output = ()> {}
    |                                            ~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:36:1
+  --> $DIR/manual_async_fn.rs:35:1
    |
 LL | fn core_fut() -> impl core::future::Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -105,7 +105,7 @@ LL | fn core_fut() -> impl core::future::Future<Output = i32> { 42 }
    |                                                          ~~~~~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:58:5
+  --> $DIR/manual_async_fn.rs:57:5
    |
 LL |     fn inh_fut() -> impl Future<Output = i32> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -125,7 +125,7 @@ LL +             let c = 21;
  ...
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:93:1
+  --> $DIR/manual_async_fn.rs:92:1
    |
 LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -140,7 +140,7 @@ LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ { 42 }
    |                                                      ~~~~~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> $DIR/manual_async_fn.rs:102:1
+  --> $DIR/manual_async_fn.rs:101:1
    |
 LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/manual_map_option.fixed b/src/tools/clippy/tests/ui/manual_map_option.fixed
index 40d01df6379..294d79abc04 100644
--- a/src/tools/clippy/tests/ui/manual_map_option.fixed
+++ b/src/tools/clippy/tests/ui/manual_map_option.fixed
@@ -1,4 +1,3 @@
-// edition:2018
 // run-rustfix
 
 #![warn(clippy::manual_map)]
diff --git a/src/tools/clippy/tests/ui/manual_map_option.rs b/src/tools/clippy/tests/ui/manual_map_option.rs
index cfef0c5cc4e..d11bf5ecb82 100644
--- a/src/tools/clippy/tests/ui/manual_map_option.rs
+++ b/src/tools/clippy/tests/ui/manual_map_option.rs
@@ -1,4 +1,3 @@
-// edition:2018
 // run-rustfix
 
 #![warn(clippy::manual_map)]
diff --git a/src/tools/clippy/tests/ui/manual_map_option.stderr b/src/tools/clippy/tests/ui/manual_map_option.stderr
index cdc2c0e62a9..0036b8151de 100644
--- a/src/tools/clippy/tests/ui/manual_map_option.stderr
+++ b/src/tools/clippy/tests/ui/manual_map_option.stderr
@@ -1,5 +1,5 @@
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:15:5
+  --> $DIR/manual_map_option.rs:14:5
    |
 LL | /     match Some(0) {
 LL | |         Some(_) => Some(2),
@@ -10,7 +10,7 @@ LL | |     };
    = note: `-D clippy::manual-map` implied by `-D warnings`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:20:5
+  --> $DIR/manual_map_option.rs:19:5
    |
 LL | /     match Some(0) {
 LL | |         Some(x) => Some(x + 1),
@@ -19,7 +19,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| x + 1)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:25:5
+  --> $DIR/manual_map_option.rs:24:5
    |
 LL | /     match Some("") {
 LL | |         Some(x) => Some(x.is_empty()),
@@ -28,7 +28,7 @@ LL | |     };
    | |_____^ help: try this: `Some("").map(|x| x.is_empty())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:30:5
+  --> $DIR/manual_map_option.rs:29:5
    |
 LL | /     if let Some(x) = Some(0) {
 LL | |         Some(!x)
@@ -38,7 +38,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| !x)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:37:5
+  --> $DIR/manual_map_option.rs:36:5
    |
 LL | /     match Some(0) {
 LL | |         Some(x) => { Some(std::convert::identity(x)) }
@@ -47,7 +47,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(std::convert::identity)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:42:5
+  --> $DIR/manual_map_option.rs:41:5
    |
 LL | /     match Some(&String::new()) {
 LL | |         Some(x) => Some(str::len(x)),
@@ -56,7 +56,7 @@ LL | |     };
    | |_____^ help: try this: `Some(&String::new()).map(|x| str::len(x))`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:52:5
+  --> $DIR/manual_map_option.rs:51:5
    |
 LL | /     match &Some([0, 1]) {
 LL | |         Some(x) => Some(x[0]),
@@ -65,7 +65,7 @@ LL | |     };
    | |_____^ help: try this: `Some([0, 1]).as_ref().map(|x| x[0])`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:57:5
+  --> $DIR/manual_map_option.rs:56:5
    |
 LL | /     match &Some(0) {
 LL | |         &Some(x) => Some(x * 2),
@@ -74,7 +74,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| x * 2)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:62:5
+  --> $DIR/manual_map_option.rs:61:5
    |
 LL | /     match Some(String::new()) {
 LL | |         Some(ref x) => Some(x.is_empty()),
@@ -83,7 +83,7 @@ LL | |     };
    | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.is_empty())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:67:5
+  --> $DIR/manual_map_option.rs:66:5
    |
 LL | /     match &&Some(String::new()) {
 LL | |         Some(x) => Some(x.len()),
@@ -92,7 +92,7 @@ LL | |     };
    | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.len())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:72:5
+  --> $DIR/manual_map_option.rs:71:5
    |
 LL | /     match &&Some(0) {
 LL | |         &&Some(x) => Some(x + x),
@@ -101,7 +101,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| x + x)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:85:9
+  --> $DIR/manual_map_option.rs:84:9
    |
 LL | /         match &mut Some(String::new()) {
 LL | |             Some(x) => Some(x.push_str("")),
@@ -110,7 +110,7 @@ LL | |         };
    | |_________^ help: try this: `Some(String::new()).as_mut().map(|x| x.push_str(""))`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:91:5
+  --> $DIR/manual_map_option.rs:90:5
    |
 LL | /     match &mut Some(String::new()) {
 LL | |         Some(ref x) => Some(x.len()),
@@ -119,7 +119,7 @@ LL | |     };
    | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.len())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:96:5
+  --> $DIR/manual_map_option.rs:95:5
    |
 LL | /     match &mut &Some(String::new()) {
 LL | |         Some(x) => Some(x.is_empty()),
@@ -128,7 +128,7 @@ LL | |     };
    | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.is_empty())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:101:5
+  --> $DIR/manual_map_option.rs:100:5
    |
 LL | /     match Some((0, 1, 2)) {
 LL | |         Some((x, y, z)) => Some(x + y + z),
@@ -137,7 +137,7 @@ LL | |     };
    | |_____^ help: try this: `Some((0, 1, 2)).map(|(x, y, z)| x + y + z)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:106:5
+  --> $DIR/manual_map_option.rs:105:5
    |
 LL | /     match Some([1, 2, 3]) {
 LL | |         Some([first, ..]) => Some(first),
@@ -146,7 +146,7 @@ LL | |     };
    | |_____^ help: try this: `Some([1, 2, 3]).map(|[first, ..]| first)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:111:5
+  --> $DIR/manual_map_option.rs:110:5
    |
 LL | /     match &Some((String::new(), "test")) {
 LL | |         Some((x, y)) => Some((y, x)),
@@ -155,7 +155,7 @@ LL | |     };
    | |_____^ help: try this: `Some((String::new(), "test")).as_ref().map(|(x, y)| (y, x))`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:169:5
+  --> $DIR/manual_map_option.rs:168:5
    |
 LL | /     match Some(0) {
 LL | |         Some(x) => Some(vec![x]),
@@ -164,7 +164,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| vec![x])`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:174:5
+  --> $DIR/manual_map_option.rs:173:5
    |
 LL | /     match option_env!("") {
 LL | |         Some(x) => Some(String::from(x)),
@@ -173,7 +173,7 @@ LL | |     };
    | |_____^ help: try this: `option_env!("").map(String::from)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:194:12
+  --> $DIR/manual_map_option.rs:193:12
    |
 LL |       } else if let Some(x) = Some(0) {
    |  ____________^
@@ -184,7 +184,7 @@ LL | |     };
    | |_____^ help: try this: `{ Some(0).map(|x| x + 1) }`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:202:12
+  --> $DIR/manual_map_option.rs:201:12
    |
 LL |       } else if let Some(x) = Some(0) {
    |  ____________^
diff --git a/src/tools/clippy/tests/ui/match_overlapping_arm.rs b/src/tools/clippy/tests/ui/match_overlapping_arm.rs
index ff91c4498ec..845986a4ead 100644
--- a/src/tools/clippy/tests/ui/match_overlapping_arm.rs
+++ b/src/tools/clippy/tests/ui/match_overlapping_arm.rs
@@ -100,6 +100,13 @@ fn overlapping() {
         _ => (),
     }
 
+    // Issue #7829
+    match 0 {
+        -1..=1 => (),
+        -2..=2 => (),
+        _ => (),
+    }
+
     if let None = Some(42) {
         // nothing
     } else if let None = Some(42) {
diff --git a/src/tools/clippy/tests/ui/match_ref_pats.rs b/src/tools/clippy/tests/ui/match_ref_pats.rs
index 50246486bb6..7e3674ab8c9 100644
--- a/src/tools/clippy/tests/ui/match_ref_pats.rs
+++ b/src/tools/clippy/tests/ui/match_ref_pats.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::match_ref_pats)]
-#![allow(clippy::equatable_if_let)]
+#![allow(clippy::equatable_if_let, clippy::enum_variant_names)]
 
 fn ref_pats() {
     {
diff --git a/src/tools/clippy/tests/ui/match_str_case_mismatch.rs b/src/tools/clippy/tests/ui/match_str_case_mismatch.rs
index 208a4bba3d2..ac555c87d83 100644
--- a/src/tools/clippy/tests/ui/match_str_case_mismatch.rs
+++ b/src/tools/clippy/tests/ui/match_str_case_mismatch.rs
@@ -12,6 +12,49 @@ fn as_str_match() {
     }
 }
 
+fn non_alphabetic() {
+    let var = "~!@#$%^&*()-_=+FOO";
+
+    match var.to_ascii_lowercase().as_str() {
+        "1234567890" => {},
+        "~!@#$%^&*()-_=+foo" => {},
+        "\n\r\t\x7F" => {},
+        _ => {},
+    }
+}
+
+fn unicode_cased() {
+    let var = "ВОДЫ";
+
+    match var.to_lowercase().as_str() {
+        "水" => {},
+        "νερό" => {},
+        "воды" => {},
+        "물" => {},
+        _ => {},
+    }
+}
+
+fn titlecase() {
+    let var = "BarDz";
+
+    match var.to_lowercase().as_str() {
+        "foolj" => {},
+        "bardz" => {},
+        _ => {},
+    }
+}
+
+fn no_case_equivalent() {
+    let var = "barʁ";
+
+    match var.to_uppercase().as_str() {
+        "FOOɕ" => {},
+        "BARʁ" => {},
+        _ => {},
+    }
+}
+
 fn addrof_unary_match() {
     let var = "BAR";
 
@@ -70,6 +113,49 @@ fn as_str_match_mismatch() {
     }
 }
 
+fn non_alphabetic_mismatch() {
+    let var = "~!@#$%^&*()-_=+FOO";
+
+    match var.to_ascii_lowercase().as_str() {
+        "1234567890" => {},
+        "~!@#$%^&*()-_=+Foo" => {},
+        "\n\r\t\x7F" => {},
+        _ => {},
+    }
+}
+
+fn unicode_cased_mismatch() {
+    let var = "ВОДЫ";
+
+    match var.to_lowercase().as_str() {
+        "水" => {},
+        "νερό" => {},
+        "Воды" => {},
+        "물" => {},
+        _ => {},
+    }
+}
+
+fn titlecase_mismatch() {
+    let var = "BarDz";
+
+    match var.to_lowercase().as_str() {
+        "foolj" => {},
+        "barDz" => {},
+        _ => {},
+    }
+}
+
+fn no_case_equivalent_mismatch() {
+    let var = "barʁ";
+
+    match var.to_uppercase().as_str() {
+        "FOOɕ" => {},
+        "bARʁ" => {},
+        _ => {},
+    }
+}
+
 fn addrof_unary_match_mismatch() {
     let var = "BAR";
 
diff --git a/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr b/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr
index fa023477a9c..92baa40ef28 100644
--- a/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr
+++ b/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr
@@ -1,5 +1,5 @@
 error: this `match` arm has a differing case than its expression
-  --> $DIR/match_str_case_mismatch.rs:68:9
+  --> $DIR/match_str_case_mismatch.rs:111:9
    |
 LL |         "Bar" => {},
    |         ^^^^^
@@ -11,7 +11,51 @@ LL |         "bar" => {},
    |         ~~~~~
 
 error: this `match` arm has a differing case than its expression
-  --> $DIR/match_str_case_mismatch.rs:78:9
+  --> $DIR/match_str_case_mismatch.rs:121:9
+   |
+LL |         "~!@#$%^&*()-_=+Foo" => {},
+   |         ^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider changing the case of this arm to respect `to_ascii_lowercase`
+   |
+LL |         "~!@#$%^&*()-_=+foo" => {},
+   |         ~~~~~~~~~~~~~~~~~~~~
+
+error: this `match` arm has a differing case than its expression
+  --> $DIR/match_str_case_mismatch.rs:133:9
+   |
+LL |         "Воды" => {},
+   |         ^^^^^^
+   |
+help: consider changing the case of this arm to respect `to_lowercase`
+   |
+LL |         "воды" => {},
+   |         ~~~~~~
+
+error: this `match` arm has a differing case than its expression
+  --> $DIR/match_str_case_mismatch.rs:144:9
+   |
+LL |         "barDz" => {},
+   |         ^^^^^^
+   |
+help: consider changing the case of this arm to respect `to_lowercase`
+   |
+LL |         "bardz" => {},
+   |         ~~~~~~
+
+error: this `match` arm has a differing case than its expression
+  --> $DIR/match_str_case_mismatch.rs:154:9
+   |
+LL |         "bARʁ" => {},
+   |         ^^^^^^
+   |
+help: consider changing the case of this arm to respect `to_uppercase`
+   |
+LL |         "BARʁ" => {},
+   |         ~~~~~~
+
+error: this `match` arm has a differing case than its expression
+  --> $DIR/match_str_case_mismatch.rs:164:9
    |
 LL |         "Bar" => {},
    |         ^^^^^
@@ -22,7 +66,7 @@ LL |         "bar" => {},
    |         ~~~~~
 
 error: this `match` arm has a differing case than its expression
-  --> $DIR/match_str_case_mismatch.rs:93:9
+  --> $DIR/match_str_case_mismatch.rs:179:9
    |
 LL |         "bAR" => {},
    |         ^^^^^
@@ -32,5 +76,5 @@ help: consider changing the case of this arm to respect `to_ascii_uppercase`
 LL |         "BAR" => {},
    |         ~~~~~
 
-error: aborting due to 3 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/match_wild_err_arm.stderr b/src/tools/clippy/tests/ui/match_wild_err_arm.edition2018.stderr
index 6a2a02987de..2a4012039ba 100644
--- a/src/tools/clippy/tests/ui/match_wild_err_arm.stderr
+++ b/src/tools/clippy/tests/ui/match_wild_err_arm.edition2018.stderr
@@ -1,5 +1,5 @@
 error: `Err(_)` matches all errors
-  --> $DIR/match_wild_err_arm.rs:11:9
+  --> $DIR/match_wild_err_arm.rs:14:9
    |
 LL |         Err(_) => panic!("err"),
    |         ^^^^^^
@@ -8,7 +8,7 @@ LL |         Err(_) => panic!("err"),
    = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
 
 error: `Err(_)` matches all errors
-  --> $DIR/match_wild_err_arm.rs:17:9
+  --> $DIR/match_wild_err_arm.rs:20:9
    |
 LL |         Err(_) => panic!(),
    |         ^^^^^^
@@ -16,7 +16,7 @@ LL |         Err(_) => panic!(),
    = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
 
 error: `Err(_)` matches all errors
-  --> $DIR/match_wild_err_arm.rs:23:9
+  --> $DIR/match_wild_err_arm.rs:26:9
    |
 LL |         Err(_) => {
    |         ^^^^^^
@@ -24,7 +24,7 @@ LL |         Err(_) => {
    = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
 
 error: `Err(_e)` matches all errors
-  --> $DIR/match_wild_err_arm.rs:31:9
+  --> $DIR/match_wild_err_arm.rs:34:9
    |
 LL |         Err(_e) => panic!(),
    |         ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/match_wild_err_arm.edition2021.stderr b/src/tools/clippy/tests/ui/match_wild_err_arm.edition2021.stderr
new file mode 100644
index 00000000000..2a4012039ba
--- /dev/null
+++ b/src/tools/clippy/tests/ui/match_wild_err_arm.edition2021.stderr
@@ -0,0 +1,35 @@
+error: `Err(_)` matches all errors
+  --> $DIR/match_wild_err_arm.rs:14:9
+   |
+LL |         Err(_) => panic!("err"),
+   |         ^^^^^^
+   |
+   = note: `-D clippy::match-wild-err-arm` implied by `-D warnings`
+   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_)` matches all errors
+  --> $DIR/match_wild_err_arm.rs:20:9
+   |
+LL |         Err(_) => panic!(),
+   |         ^^^^^^
+   |
+   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_)` matches all errors
+  --> $DIR/match_wild_err_arm.rs:26:9
+   |
+LL |         Err(_) => {
+   |         ^^^^^^
+   |
+   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_e)` matches all errors
+  --> $DIR/match_wild_err_arm.rs:34:9
+   |
+LL |         Err(_e) => panic!(),
+   |         ^^^^^^^
+   |
+   = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/match_wild_err_arm.rs b/src/tools/clippy/tests/ui/match_wild_err_arm.rs
index 823be65efe0..0a86144b95d 100644
--- a/src/tools/clippy/tests/ui/match_wild_err_arm.rs
+++ b/src/tools/clippy/tests/ui/match_wild_err_arm.rs
@@ -1,3 +1,6 @@
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
 #![feature(exclusive_range_pattern)]
 #![allow(clippy::match_same_arms)]
 #![warn(clippy::match_wild_err_arm)]
diff --git a/src/tools/clippy/tests/ui/methods.rs b/src/tools/clippy/tests/ui/methods.rs
index c441b35b992..977ce54327b 100644
--- a/src/tools/clippy/tests/ui/methods.rs
+++ b/src/tools/clippy/tests/ui/methods.rs
@@ -1,5 +1,4 @@
 // aux-build:option_helpers.rs
-// edition:2018
 
 #![warn(clippy::all, clippy::pedantic)]
 #![allow(
diff --git a/src/tools/clippy/tests/ui/methods.stderr b/src/tools/clippy/tests/ui/methods.stderr
index 4643e09e270..b63672dd6fd 100644
--- a/src/tools/clippy/tests/ui/methods.stderr
+++ b/src/tools/clippy/tests/ui/methods.stderr
@@ -1,5 +1,5 @@
 error: methods called `new` usually return `Self`
-  --> $DIR/methods.rs:105:5
+  --> $DIR/methods.rs:104:5
    |
 LL | /     fn new() -> i32 {
 LL | |         0
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::new-ret-no-self` implied by `-D warnings`
 
 error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead
-  --> $DIR/methods.rs:126:13
+  --> $DIR/methods.rs:125:13
    |
 LL |       let _ = v.iter().filter(|&x| {
    |  _____________^
diff --git a/src/tools/clippy/tests/ui/missing-doc.rs b/src/tools/clippy/tests/ui/missing-doc.rs
index a9bf7140a1e..148531c285d 100644
--- a/src/tools/clippy/tests/ui/missing-doc.rs
+++ b/src/tools/clippy/tests/ui/missing-doc.rs
@@ -3,7 +3,6 @@
 // injected intrinsics by the compiler.
 #![allow(dead_code)]
 #![feature(global_asm)]
-
 //! Some garbage docs for the crate here
 #![doc = "More garbage"]
 
@@ -90,10 +89,10 @@ mod internal_impl {
 }
 /// dox
 pub mod public_interface {
-    pub use internal_impl::documented as foo;
-    pub use internal_impl::globbed::*;
-    pub use internal_impl::undocumented1 as bar;
-    pub use internal_impl::{documented, undocumented2};
+    pub use crate::internal_impl::documented as foo;
+    pub use crate::internal_impl::globbed::*;
+    pub use crate::internal_impl::undocumented1 as bar;
+    pub use crate::internal_impl::{documented, undocumented2};
 }
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/missing-doc.stderr b/src/tools/clippy/tests/ui/missing-doc.stderr
index a876dc078eb..7a3a448c9d6 100644
--- a/src/tools/clippy/tests/ui/missing-doc.stderr
+++ b/src/tools/clippy/tests/ui/missing-doc.stderr
@@ -1,5 +1,5 @@
 error: missing documentation for a type alias
-  --> $DIR/missing-doc.rs:10:1
+  --> $DIR/missing-doc.rs:9:1
    |
 LL | type Typedef = String;
    | ^^^^^^^^^^^^^^^^^^^^^^
@@ -7,37 +7,37 @@ LL | type Typedef = String;
    = note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings`
 
 error: missing documentation for a type alias
-  --> $DIR/missing-doc.rs:11:1
+  --> $DIR/missing-doc.rs:10:1
    |
 LL | pub type PubTypedef = String;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a module
-  --> $DIR/missing-doc.rs:13:1
+  --> $DIR/missing-doc.rs:12:1
    |
 LL | mod module_no_dox {}
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a module
-  --> $DIR/missing-doc.rs:14:1
+  --> $DIR/missing-doc.rs:13:1
    |
 LL | pub mod pub_module_no_dox {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> $DIR/missing-doc.rs:18:1
+  --> $DIR/missing-doc.rs:17:1
    |
 LL | pub fn foo2() {}
    | ^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> $DIR/missing-doc.rs:19:1
+  --> $DIR/missing-doc.rs:18:1
    |
 LL | fn foo3() {}
    | ^^^^^^^^^^^^
 
 error: missing documentation for an enum
-  --> $DIR/missing-doc.rs:33:1
+  --> $DIR/missing-doc.rs:32:1
    |
 LL | / enum Baz {
 LL | |     BazA { a: isize, b: isize },
@@ -46,31 +46,31 @@ LL | | }
    | |_^
 
 error: missing documentation for a variant
-  --> $DIR/missing-doc.rs:34:5
+  --> $DIR/missing-doc.rs:33:5
    |
 LL |     BazA { a: isize, b: isize },
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a struct field
-  --> $DIR/missing-doc.rs:34:12
+  --> $DIR/missing-doc.rs:33:12
    |
 LL |     BazA { a: isize, b: isize },
    |            ^^^^^^^^
 
 error: missing documentation for a struct field
-  --> $DIR/missing-doc.rs:34:22
+  --> $DIR/missing-doc.rs:33:22
    |
 LL |     BazA { a: isize, b: isize },
    |                      ^^^^^^^^
 
 error: missing documentation for a variant
-  --> $DIR/missing-doc.rs:35:5
+  --> $DIR/missing-doc.rs:34:5
    |
 LL |     BarB,
    |     ^^^^
 
 error: missing documentation for an enum
-  --> $DIR/missing-doc.rs:38:1
+  --> $DIR/missing-doc.rs:37:1
    |
 LL | / pub enum PubBaz {
 LL | |     PubBazA { a: isize },
@@ -78,43 +78,43 @@ LL | | }
    | |_^
 
 error: missing documentation for a variant
-  --> $DIR/missing-doc.rs:39:5
+  --> $DIR/missing-doc.rs:38:5
    |
 LL |     PubBazA { a: isize },
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a struct field
-  --> $DIR/missing-doc.rs:39:15
+  --> $DIR/missing-doc.rs:38:15
    |
 LL |     PubBazA { a: isize },
    |               ^^^^^^^^
 
 error: missing documentation for a constant
-  --> $DIR/missing-doc.rs:59:1
+  --> $DIR/missing-doc.rs:58:1
    |
 LL | const FOO: u32 = 0;
    | ^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a constant
-  --> $DIR/missing-doc.rs:66:1
+  --> $DIR/missing-doc.rs:65:1
    |
 LL | pub const FOO4: u32 = 0;
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a static
-  --> $DIR/missing-doc.rs:68:1
+  --> $DIR/missing-doc.rs:67:1
    |
 LL | static BAR: u32 = 0;
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a static
-  --> $DIR/missing-doc.rs:75:1
+  --> $DIR/missing-doc.rs:74:1
    |
 LL | pub static BAR4: u32 = 0;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a module
-  --> $DIR/missing-doc.rs:77:1
+  --> $DIR/missing-doc.rs:76:1
    |
 LL | / mod internal_impl {
 LL | |     /// dox
@@ -126,31 +126,31 @@ LL | | }
    | |_^
 
 error: missing documentation for a function
-  --> $DIR/missing-doc.rs:80:5
+  --> $DIR/missing-doc.rs:79:5
    |
 LL |     pub fn undocumented1() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> $DIR/missing-doc.rs:81:5
+  --> $DIR/missing-doc.rs:80:5
    |
 LL |     pub fn undocumented2() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> $DIR/missing-doc.rs:82:5
+  --> $DIR/missing-doc.rs:81:5
    |
 LL |     fn undocumented3() {}
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> $DIR/missing-doc.rs:87:9
+  --> $DIR/missing-doc.rs:86:9
    |
 LL |         pub fn also_undocumented1() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> $DIR/missing-doc.rs:88:9
+  --> $DIR/missing-doc.rs:87:9
    |
 LL |         fn also_undocumented2() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/missing_panics_doc.rs b/src/tools/clippy/tests/ui/missing_panics_doc.rs
index 2e1379a58a6..7dc44529206 100644
--- a/src/tools/clippy/tests/ui/missing_panics_doc.rs
+++ b/src/tools/clippy/tests/ui/missing_panics_doc.rs
@@ -1,6 +1,5 @@
 #![warn(clippy::missing_panics_doc)]
 #![allow(clippy::option_map_unit_fn)]
-
 fn main() {}
 
 /// This needs to be documented
diff --git a/src/tools/clippy/tests/ui/missing_panics_doc.stderr b/src/tools/clippy/tests/ui/missing_panics_doc.stderr
index b863063b626..60282939ef0 100644
--- a/src/tools/clippy/tests/ui/missing_panics_doc.stderr
+++ b/src/tools/clippy/tests/ui/missing_panics_doc.stderr
@@ -1,5 +1,5 @@
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:7:1
+  --> $DIR/missing_panics_doc.rs:6:1
    |
 LL | / pub fn unwrap() {
 LL | |     let result = Err("Hi");
@@ -9,13 +9,13 @@ LL | | }
    |
    = note: `-D clippy::missing-panics-doc` implied by `-D warnings`
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:9:5
+  --> $DIR/missing_panics_doc.rs:8:5
    |
 LL |     result.unwrap()
    |     ^^^^^^^^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:13:1
+  --> $DIR/missing_panics_doc.rs:12:1
    |
 LL | / pub fn panic() {
 LL | |     panic!("This function panics")
@@ -23,14 +23,14 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:14:5
+  --> $DIR/missing_panics_doc.rs:13:5
    |
 LL |     panic!("This function panics")
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:18:1
+  --> $DIR/missing_panics_doc.rs:17:1
    |
 LL | / pub fn todo() {
 LL | |     todo!()
@@ -38,14 +38,14 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:19:5
+  --> $DIR/missing_panics_doc.rs:18:5
    |
 LL |     todo!()
    |     ^^^^^^^
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:23:1
+  --> $DIR/missing_panics_doc.rs:22:1
    |
 LL | / pub fn inner_body(opt: Option<u32>) {
 LL | |     opt.map(|x| {
@@ -57,14 +57,14 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:26:13
+  --> $DIR/missing_panics_doc.rs:25:13
    |
 LL |             panic!()
    |             ^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:32:1
+  --> $DIR/missing_panics_doc.rs:31:1
    |
 LL | / pub fn unreachable_and_panic() {
 LL | |     if true { unreachable!() } else { panic!() }
@@ -72,14 +72,14 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:33:39
+  --> $DIR/missing_panics_doc.rs:32:39
    |
 LL |     if true { unreachable!() } else { panic!() }
    |                                       ^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:37:1
+  --> $DIR/missing_panics_doc.rs:36:1
    |
 LL | / pub fn assert_eq() {
 LL | |     let x = 0;
@@ -88,14 +88,14 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:39:5
+  --> $DIR/missing_panics_doc.rs:38:5
    |
 LL |     assert_eq!(x, 0);
    |     ^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:43:1
+  --> $DIR/missing_panics_doc.rs:42:1
    |
 LL | / pub fn assert_ne() {
 LL | |     let x = 0;
@@ -104,7 +104,7 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:45:5
+  --> $DIR/missing_panics_doc.rs:44:5
    |
 LL |     assert_ne!(x, 0);
    |     ^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_borrow_pat.rs b/src/tools/clippy/tests/ui/needless_borrow_pat.rs
index 7a8137778b4..04b6283da3c 100644
--- a/src/tools/clippy/tests/ui/needless_borrow_pat.rs
+++ b/src/tools/clippy/tests/ui/needless_borrow_pat.rs
@@ -1,4 +1,3 @@
-// edition:2018
 // FIXME: run-rustfix waiting on multi-span suggestions
 
 #![warn(clippy::needless_borrow)]
diff --git a/src/tools/clippy/tests/ui/needless_borrow_pat.stderr b/src/tools/clippy/tests/ui/needless_borrow_pat.stderr
index 365ecd68d8f..db3b52b8850 100644
--- a/src/tools/clippy/tests/ui/needless_borrow_pat.stderr
+++ b/src/tools/clippy/tests/ui/needless_borrow_pat.stderr
@@ -1,5 +1,5 @@
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:60:14
+  --> $DIR/needless_borrow_pat.rs:59:14
    |
 LL |         Some(ref x) => x,
    |              ^^^^^ help: try this: `x`
@@ -7,7 +7,7 @@ LL |         Some(ref x) => x,
    = note: `-D clippy::needless-borrow` implied by `-D warnings`
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:66:14
+  --> $DIR/needless_borrow_pat.rs:65:14
    |
 LL |         Some(ref x) => *x,
    |              ^^^^^
@@ -18,7 +18,7 @@ LL |         Some(x) => x,
    |              ~     ~
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:72:14
+  --> $DIR/needless_borrow_pat.rs:71:14
    |
 LL |         Some(ref x) => {
    |              ^^^^^
@@ -31,19 +31,19 @@ LL ~             f1(x);
    |
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:82:14
+  --> $DIR/needless_borrow_pat.rs:81:14
    |
 LL |         Some(ref x) => m1!(x),
    |              ^^^^^ help: try this: `x`
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:87:15
+  --> $DIR/needless_borrow_pat.rs:86:15
    |
 LL |     let _ = |&ref x: &&String| {
    |               ^^^^^ help: try this: `x`
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:92:10
+  --> $DIR/needless_borrow_pat.rs:91:10
    |
 LL |     let (ref y,) = (&x,);
    |          ^^^^^
@@ -55,13 +55,13 @@ LL ~     let _: &String = y;
    |
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:102:14
+  --> $DIR/needless_borrow_pat.rs:101:14
    |
 LL |         Some(ref x) => x.0,
    |              ^^^^^ help: try this: `x`
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:112:14
+  --> $DIR/needless_borrow_pat.rs:111:14
    |
 LL |         E::A(ref x) | E::B(ref x) => *x,
    |              ^^^^^         ^^^^^
@@ -72,13 +72,13 @@ LL |         E::A(x) | E::B(x) => x,
    |              ~         ~     ~
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:118:21
+  --> $DIR/needless_borrow_pat.rs:117:21
    |
 LL |         if let Some(ref x) = Some(&String::new());
    |                     ^^^^^ help: try this: `x`
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:126:12
+  --> $DIR/needless_borrow_pat.rs:125:12
    |
 LL | fn f2<'a>(&ref x: &&'a String) -> &'a String {
    |            ^^^^^
@@ -91,13 +91,13 @@ LL ~     x
    |
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:133:11
+  --> $DIR/needless_borrow_pat.rs:132:11
    |
 LL |     fn f(&ref x: &&String) {
    |           ^^^^^ help: try this: `x`
 
 error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow_pat.rs:141:11
+  --> $DIR/needless_borrow_pat.rs:140:11
    |
 LL |     fn f(&ref x: &&String) {
    |           ^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.rs b/src/tools/clippy/tests/ui/needless_lifetimes.rs
index 1d77382bf2c..b07c4a23810 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.rs
@@ -27,6 +27,11 @@ fn multiple_in_and_out_2<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
     x
 }
 
+// No error; multiple input refs
+async fn func<'a>(args: &[&'a str]) -> Option<&'a str> {
+    args.get(0).cloned()
+}
+
 // No error; static involved.
 fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 {
     x
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.stderr b/src/tools/clippy/tests/ui/needless_lifetimes.stderr
index 33a6de1618d..4114e6f1832 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.stderr
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.stderr
@@ -19,133 +19,133 @@ LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:45:1
+  --> $DIR/needless_lifetimes.rs:50:1
    |
 LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:50:1
+  --> $DIR/needless_lifetimes.rs:55:1
    |
 LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:62:1
+  --> $DIR/needless_lifetimes.rs:67:1
    |
 LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:86:1
+  --> $DIR/needless_lifetimes.rs:91:1
    |
 LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:116:5
+  --> $DIR/needless_lifetimes.rs:121:5
    |
 LL |     fn self_and_out<'s>(&'s self) -> &'s u8 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:125:5
+  --> $DIR/needless_lifetimes.rs:130:5
    |
 LL |     fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:144:1
+  --> $DIR/needless_lifetimes.rs:149:1
    |
 LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:174:1
+  --> $DIR/needless_lifetimes.rs:179:1
    |
 LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:180:1
+  --> $DIR/needless_lifetimes.rs:185:1
    |
 LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:199:1
+  --> $DIR/needless_lifetimes.rs:204:1
    |
 LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:207:1
+  --> $DIR/needless_lifetimes.rs:212:1
    |
 LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:243:1
+  --> $DIR/needless_lifetimes.rs:248:1
    |
 LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:250:9
+  --> $DIR/needless_lifetimes.rs:255:9
    |
 LL |         fn needless_lt<'a>(x: &'a u8) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:254:9
+  --> $DIR/needless_lifetimes.rs:259:9
    |
 LL |         fn needless_lt<'a>(_x: &'a u8) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:267:9
+  --> $DIR/needless_lifetimes.rs:272:9
    |
 LL |         fn baz<'a>(&'a self) -> impl Foo + 'a {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:296:5
+  --> $DIR/needless_lifetimes.rs:301:5
    |
 LL |     fn impl_trait_elidable_nested_named_lifetimes<'a>(i: &'a i32, f: impl for<'b> Fn(&'b i32) -> &'b i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:299:5
+  --> $DIR/needless_lifetimes.rs:304:5
    |
 LL |     fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:308:5
+  --> $DIR/needless_lifetimes.rs:313:5
    |
 LL |     fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:320:5
+  --> $DIR/needless_lifetimes.rs:325:5
    |
 LL |     fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:335:5
+  --> $DIR/needless_lifetimes.rs:340:5
    |
 LL |     fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:348:5
+  --> $DIR/needless_lifetimes.rs:353:5
    |
 LL |     fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:351:5
+  --> $DIR/needless_lifetimes.rs:356:5
    |
 LL |     fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index 9c999e12b4c..812ce7163cd 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 
 #![feature(let_else)]
 #![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index da7dcf4f0a9..c42567b517c 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 
 #![feature(let_else)]
 #![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr
index 2e802cff1e6..74dda971fda 100644
--- a/src/tools/clippy/tests/ui/needless_return.stderr
+++ b/src/tools/clippy/tests/ui/needless_return.stderr
@@ -1,5 +1,5 @@
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:25:5
+  --> $DIR/needless_return.rs:24:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
@@ -7,187 +7,187 @@ LL |     return true;
    = note: `-D clippy::needless-return` implied by `-D warnings`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:29:5
+  --> $DIR/needless_return.rs:28:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:34:9
+  --> $DIR/needless_return.rs:33:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:36:9
+  --> $DIR/needless_return.rs:35:9
    |
 LL |         return false;
    |         ^^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:42:17
+  --> $DIR/needless_return.rs:41:17
    |
 LL |         true => return false,
    |                 ^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:44:13
+  --> $DIR/needless_return.rs:43:13
    |
 LL |             return true;
    |             ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:51:9
+  --> $DIR/needless_return.rs:50:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:53:16
+  --> $DIR/needless_return.rs:52:16
    |
 LL |     let _ = || return true;
    |                ^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:61:5
+  --> $DIR/needless_return.rs:60:5
    |
 LL |     return;
    |     ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:66:9
+  --> $DIR/needless_return.rs:65:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:68:9
+  --> $DIR/needless_return.rs:67:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:75:14
+  --> $DIR/needless_return.rs:74:14
    |
 LL |         _ => return,
    |              ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:90:9
+  --> $DIR/needless_return.rs:89:9
    |
 LL |         return String::from("test");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:92:9
+  --> $DIR/needless_return.rs:91:9
    |
 LL |         return String::new();
    |         ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:113:32
+  --> $DIR/needless_return.rs:112:32
    |
 LL |         bar.unwrap_or_else(|_| return)
    |                                ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:118:13
+  --> $DIR/needless_return.rs:117:13
    |
 LL |             return;
    |             ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:120:20
+  --> $DIR/needless_return.rs:119:20
    |
 LL |         let _ = || return;
    |                    ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:126:32
+  --> $DIR/needless_return.rs:125:32
    |
 LL |         res.unwrap_or_else(|_| return Foo)
    |                                ^^^^^^^^^^ help: remove `return`: `Foo`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:135:5
+  --> $DIR/needless_return.rs:134:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:139:5
+  --> $DIR/needless_return.rs:138:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:144:9
+  --> $DIR/needless_return.rs:143:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:146:9
+  --> $DIR/needless_return.rs:145:9
    |
 LL |         return false;
    |         ^^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:152:17
+  --> $DIR/needless_return.rs:151:17
    |
 LL |         true => return false,
    |                 ^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:154:13
+  --> $DIR/needless_return.rs:153:13
    |
 LL |             return true;
    |             ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:161:9
+  --> $DIR/needless_return.rs:160:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:163:16
+  --> $DIR/needless_return.rs:162:16
    |
 LL |     let _ = || return true;
    |                ^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:171:5
+  --> $DIR/needless_return.rs:170:5
    |
 LL |     return;
    |     ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:176:9
+  --> $DIR/needless_return.rs:175:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:178:9
+  --> $DIR/needless_return.rs:177:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:185:14
+  --> $DIR/needless_return.rs:184:14
    |
 LL |         _ => return,
    |              ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:200:9
+  --> $DIR/needless_return.rs:199:9
    |
 LL |         return String::from("test");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:202:9
+  --> $DIR/needless_return.rs:201:9
    |
 LL |         return String::new();
    |         ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
diff --git a/src/tools/clippy/tests/ui/non_expressive_names.rs b/src/tools/clippy/tests/ui/non_expressive_names.rs
index 58415b4aede..961f6f409dd 100644
--- a/src/tools/clippy/tests/ui/non_expressive_names.rs
+++ b/src/tools/clippy/tests/ui/non_expressive_names.rs
@@ -15,8 +15,8 @@ struct InstSplit {
 impl MaybeInst {
     fn fill(&mut self) {
         let filled = match *self {
-            MaybeInst::Split1(goto1) => panic!(1),
-            MaybeInst::Split2(goto2) => panic!(2),
+            MaybeInst::Split1(goto1) => panic!("1"),
+            MaybeInst::Split2(goto2) => panic!("2"),
             _ => unimplemented!(),
         };
         unimplemented!()
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed
index 4077f1920a3..9cb6a9d1ecc 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.fixed
+++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed
@@ -1,4 +1,3 @@
-// edition:2018
 // run-rustfix
 #![warn(clippy::option_if_let_else)]
 #![allow(clippy::redundant_closure, clippy::ref_option_ref, clippy::equatable_if_let)]
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs
index 2f414e129d5..b3ba5eb870a 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.rs
+++ b/src/tools/clippy/tests/ui/option_if_let_else.rs
@@ -1,4 +1,3 @@
-// edition:2018
 // run-rustfix
 #![warn(clippy::option_if_let_else)]
 #![allow(clippy::redundant_closure, clippy::ref_option_ref, clippy::equatable_if_let)]
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr
index 803d941c36d..685bb48ea37 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.stderr
+++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr
@@ -1,5 +1,5 @@
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:7:5
+  --> $DIR/option_if_let_else.rs:6:5
    |
 LL | /     if let Some(x) = string {
 LL | |         (true, x)
@@ -11,19 +11,19 @@ LL | |     }
    = note: `-D clippy::option-if-let-else` implied by `-D warnings`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:25:13
+  --> $DIR/option_if_let_else.rs:24:13
    |
 LL |     let _ = if let Some(s) = *string { s.len() } else { 0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:26:13
+  --> $DIR/option_if_let_else.rs:25:13
    |
 LL |     let _ = if let Some(s) = &num { s } else { &0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:27:13
+  --> $DIR/option_if_let_else.rs:26:13
    |
 LL |       let _ = if let Some(s) = &mut num {
    |  _____________^
@@ -43,13 +43,13 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:33:13
+  --> $DIR/option_if_let_else.rs:32:13
    |
 LL |     let _ = if let Some(ref s) = num { s } else { &0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:34:13
+  --> $DIR/option_if_let_else.rs:33:13
    |
 LL |       let _ = if let Some(mut s) = num {
    |  _____________^
@@ -69,7 +69,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:40:13
+  --> $DIR/option_if_let_else.rs:39:13
    |
 LL |       let _ = if let Some(ref mut s) = num {
    |  _____________^
@@ -89,7 +89,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:49:5
+  --> $DIR/option_if_let_else.rs:48:5
    |
 LL | /     if let Some(x) = arg {
 LL | |         let y = x * x;
@@ -108,7 +108,7 @@ LL +     })
    |
 
 error: use Option::map_or_else instead of an if let/else
-  --> $DIR/option_if_let_else.rs:62:13
+  --> $DIR/option_if_let_else.rs:61:13
    |
 LL |       let _ = if let Some(x) = arg {
    |  _____________^
@@ -120,7 +120,7 @@ LL | |     };
    | |_____^ help: try: `arg.map_or_else(|| side_effect(), |x| x)`
 
 error: use Option::map_or_else instead of an if let/else
-  --> $DIR/option_if_let_else.rs:71:13
+  --> $DIR/option_if_let_else.rs:70:13
    |
 LL |       let _ = if let Some(x) = arg {
    |  _____________^
@@ -143,13 +143,13 @@ LL ~     }, |x| x * x * x * x);
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:100:13
+  --> $DIR/option_if_let_else.rs:99:13
    |
 LL |     let _ = if let Some(x) = optional { x + 2 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:109:13
+  --> $DIR/option_if_let_else.rs:108:13
    |
 LL |       let _ = if let Some(x) = Some(0) {
    |  _____________^
@@ -171,13 +171,13 @@ LL ~         });
    |
 
 error: use Option::map_or_else instead of an if let/else
-  --> $DIR/option_if_let_else.rs:137:13
+  --> $DIR/option_if_let_else.rs:136:13
    |
 LL |     let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or_else(|| s.len(), |x| s.len() + x)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:141:13
+  --> $DIR/option_if_let_else.rs:140:13
    |
 LL |       let _ = if let Some(x) = Some(0) {
    |  _____________^
diff --git a/src/tools/clippy/tests/ui/panic_in_result_fn.rs b/src/tools/clippy/tests/ui/panic_in_result_fn.rs
index 3d3c19a1be5..e75eb1b6ead 100644
--- a/src/tools/clippy/tests/ui/panic_in_result_fn.rs
+++ b/src/tools/clippy/tests/ui/panic_in_result_fn.rs
@@ -1,6 +1,5 @@
 #![warn(clippy::panic_in_result_fn)]
 #![allow(clippy::unnecessary_wraps)]
-
 struct A;
 
 impl A {
diff --git a/src/tools/clippy/tests/ui/panic_in_result_fn.stderr b/src/tools/clippy/tests/ui/panic_in_result_fn.stderr
index f56c2d03c66..78d09b8b210 100644
--- a/src/tools/clippy/tests/ui/panic_in_result_fn.stderr
+++ b/src/tools/clippy/tests/ui/panic_in_result_fn.stderr
@@ -1,5 +1,5 @@
 error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:7:5
+  --> $DIR/panic_in_result_fn.rs:6:5
    |
 LL | /     fn result_with_panic() -> Result<bool, String> // should emit lint
 LL | |     {
@@ -10,14 +10,14 @@ LL | |     }
    = note: `-D clippy::panic-in-result-fn` implied by `-D warnings`
    = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
 note: return Err() instead of panicking
-  --> $DIR/panic_in_result_fn.rs:9:9
+  --> $DIR/panic_in_result_fn.rs:8:9
    |
 LL |         panic!("error");
    |         ^^^^^^^^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:12:5
+  --> $DIR/panic_in_result_fn.rs:11:5
    |
 LL | /     fn result_with_unimplemented() -> Result<bool, String> // should emit lint
 LL | |     {
@@ -27,14 +27,14 @@ LL | |     }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
 note: return Err() instead of panicking
-  --> $DIR/panic_in_result_fn.rs:14:9
+  --> $DIR/panic_in_result_fn.rs:13:9
    |
 LL |         unimplemented!();
    |         ^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `unimplemented` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:17:5
+  --> $DIR/panic_in_result_fn.rs:16:5
    |
 LL | /     fn result_with_unreachable() -> Result<bool, String> // should emit lint
 LL | |     {
@@ -44,14 +44,14 @@ LL | |     }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
 note: return Err() instead of panicking
-  --> $DIR/panic_in_result_fn.rs:19:9
+  --> $DIR/panic_in_result_fn.rs:18:9
    |
 LL |         unreachable!();
    |         ^^^^^^^^^^^^^^
    = note: this error originates in the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:22:5
+  --> $DIR/panic_in_result_fn.rs:21:5
    |
 LL | /     fn result_with_todo() -> Result<bool, String> // should emit lint
 LL | |     {
@@ -61,14 +61,14 @@ LL | |     }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
 note: return Err() instead of panicking
-  --> $DIR/panic_in_result_fn.rs:24:9
+  --> $DIR/panic_in_result_fn.rs:23:9
    |
 LL |         todo!("Finish this");
    |         ^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:53:1
+  --> $DIR/panic_in_result_fn.rs:52:1
    |
 LL | / fn function_result_with_panic() -> Result<bool, String> // should emit lint
 LL | | {
@@ -78,14 +78,14 @@ LL | | }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
 note: return Err() instead of panicking
-  --> $DIR/panic_in_result_fn.rs:55:5
+  --> $DIR/panic_in_result_fn.rs:54:5
    |
 LL |     panic!("error");
    |     ^^^^^^^^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
-  --> $DIR/panic_in_result_fn.rs:68:1
+  --> $DIR/panic_in_result_fn.rs:67:1
    |
 LL | / fn main() -> Result<(), String> {
 LL | |     todo!("finish main method");
@@ -95,7 +95,7 @@ LL | | }
    |
    = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
 note: return Err() instead of panicking
-  --> $DIR/panic_in_result_fn.rs:69:5
+  --> $DIR/panic_in_result_fn.rs:68:5
    |
 LL |     todo!("finish main method");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/ptr_arg.rs b/src/tools/clippy/tests/ui/ptr_arg.rs
index 99e6d2aad8d..67bfef06a05 100644
--- a/src/tools/clippy/tests/ui/ptr_arg.rs
+++ b/src/tools/clippy/tests/ui/ptr_arg.rs
@@ -1,9 +1,4 @@
-#![allow(
-    unused,
-    clippy::many_single_char_names,
-    clippy::redundant_clone,
-    clippy::if_then_panic
-)]
+#![allow(unused, clippy::many_single_char_names, clippy::redundant_clone)]
 #![warn(clippy::ptr_arg)]
 
 use std::borrow::Cow;
@@ -160,3 +155,7 @@ mod issue6509 {
         let _ = str.clone().clone();
     }
 }
+
+// No error for types behind an alias (#7699)
+type A = Vec<u8>;
+fn aliased(a: &A) {}
diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr
index 42183447ead..64594eb870c 100644
--- a/src/tools/clippy/tests/ui/ptr_arg.stderr
+++ b/src/tools/clippy/tests/ui/ptr_arg.stderr
@@ -1,5 +1,5 @@
 error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
-  --> $DIR/ptr_arg.rs:12:14
+  --> $DIR/ptr_arg.rs:7:14
    |
 LL | fn do_vec(x: &Vec<i64>) {
    |              ^^^^^^^^^ help: change this to: `&[i64]`
@@ -7,25 +7,25 @@ LL | fn do_vec(x: &Vec<i64>) {
    = note: `-D clippy::ptr-arg` implied by `-D warnings`
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:21:14
+  --> $DIR/ptr_arg.rs:16:14
    |
 LL | fn do_str(x: &String) {
    |              ^^^^^^^ help: change this to: `&str`
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:30:15
+  --> $DIR/ptr_arg.rs:25:15
    |
 LL | fn do_path(x: &PathBuf) {
    |               ^^^^^^^^ help: change this to: `&Path`
 
 error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
-  --> $DIR/ptr_arg.rs:43:18
+  --> $DIR/ptr_arg.rs:38:18
    |
 LL |     fn do_vec(x: &Vec<i64>);
    |                  ^^^^^^^^^ help: change this to: `&[i64]`
 
 error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
-  --> $DIR/ptr_arg.rs:56:14
+  --> $DIR/ptr_arg.rs:51:14
    |
 LL | fn cloned(x: &Vec<u8>) -> Vec<u8> {
    |              ^^^^^^^^
@@ -44,7 +44,7 @@ LL |     x.to_owned()
    |
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:65:18
+  --> $DIR/ptr_arg.rs:60:18
    |
 LL | fn str_cloned(x: &String) -> String {
    |                  ^^^^^^^
@@ -67,7 +67,7 @@ LL |     x.to_string()
    |
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:73:19
+  --> $DIR/ptr_arg.rs:68:19
    |
 LL | fn path_cloned(x: &PathBuf) -> PathBuf {
    |                   ^^^^^^^^
@@ -90,7 +90,7 @@ LL |     x.to_path_buf()
    |
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:81:44
+  --> $DIR/ptr_arg.rs:76:44
    |
 LL | fn false_positive_capacity(x: &Vec<u8>, y: &String) {
    |                                            ^^^^^^^
@@ -109,13 +109,13 @@ LL |     let c = y;
    |             ~
 
 error: using a reference to `Cow` is not recommended
-  --> $DIR/ptr_arg.rs:95:25
+  --> $DIR/ptr_arg.rs:90:25
    |
 LL | fn test_cow_with_ref(c: &Cow<[i32]>) {}
    |                         ^^^^^^^^^^^ help: change this to: `&[i32]`
 
 error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
-  --> $DIR/ptr_arg.rs:148:21
+  --> $DIR/ptr_arg.rs:143:21
    |
 LL |     fn foo_vec(vec: &Vec<u8>) {
    |                     ^^^^^^^^
@@ -134,7 +134,7 @@ LL |         let _ = vec.to_owned().clone();
    |                 ~~~~~~~~~~~~~~
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:153:23
+  --> $DIR/ptr_arg.rs:148:23
    |
 LL |     fn foo_path(path: &PathBuf) {
    |                       ^^^^^^^^
@@ -153,7 +153,7 @@ LL |         let _ = path.to_path_buf().clone();
    |                 ~~~~~~~~~~~~~~~~~~
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:158:21
+  --> $DIR/ptr_arg.rs:153:21
    |
 LL |     fn foo_str(str: &PathBuf) {
    |                     ^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed
index ccb2e5a302e..e93469e5f55 100644
--- a/src/tools/clippy/tests/ui/question_mark.fixed
+++ b/src/tools/clippy/tests/ui/question_mark.fixed
@@ -104,7 +104,11 @@ fn func() -> Option<i32> {
     Some(0)
 }
 
-fn result_func(x: Result<i32, &str>) -> Result<i32, &str> {
+fn func_returning_result() -> Result<i32, i32> {
+    Ok(1)
+}
+
+fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
     let _ = x?;
 
     x?;
@@ -113,9 +117,22 @@ fn result_func(x: Result<i32, &str>) -> Result<i32, &str> {
     let y = if let Ok(x) = x {
         x
     } else {
-        return Err("some error");
+        return Err(0);
+    };
+
+    // issue #7859
+    // no warning
+    let _ = if let Ok(x) = func_returning_result() {
+        x
+    } else {
+        return Err(0);
     };
 
+    // no warning
+    if func_returning_result().is_err() {
+        return func_returning_result();
+    }
+
     Ok(y)
 }
 
diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs
index ca3722371f5..dd179e9bee8 100644
--- a/src/tools/clippy/tests/ui/question_mark.rs
+++ b/src/tools/clippy/tests/ui/question_mark.rs
@@ -134,7 +134,11 @@ fn func() -> Option<i32> {
     Some(0)
 }
 
-fn result_func(x: Result<i32, &str>) -> Result<i32, &str> {
+fn func_returning_result() -> Result<i32, i32> {
+    Ok(1)
+}
+
+fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
     let _ = if let Ok(x) = x { x } else { return x };
 
     if x.is_err() {
@@ -145,9 +149,22 @@ fn result_func(x: Result<i32, &str>) -> Result<i32, &str> {
     let y = if let Ok(x) = x {
         x
     } else {
-        return Err("some error");
+        return Err(0);
+    };
+
+    // issue #7859
+    // no warning
+    let _ = if let Ok(x) = func_returning_result() {
+        x
+    } else {
+        return Err(0);
     };
 
+    // no warning
+    if func_returning_result().is_err() {
+        return func_returning_result();
+    }
+
     Ok(y)
 }
 
diff --git a/src/tools/clippy/tests/ui/question_mark.stderr b/src/tools/clippy/tests/ui/question_mark.stderr
index 161588cb73c..8d782b71dd6 100644
--- a/src/tools/clippy/tests/ui/question_mark.stderr
+++ b/src/tools/clippy/tests/ui/question_mark.stderr
@@ -101,13 +101,13 @@ LL | |     }
    | |_____^ help: replace it with: `f()?;`
 
 error: this if-let-else may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:138:13
+  --> $DIR/question_mark.rs:142:13
    |
 LL |     let _ = if let Ok(x) = x { x } else { return x };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x?`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:140:5
+  --> $DIR/question_mark.rs:144:5
    |
 LL | /     if x.is_err() {
 LL | |         return x;
diff --git a/src/tools/clippy/tests/ui/redundant_clone.fixed b/src/tools/clippy/tests/ui/redundant_clone.fixed
index 2d711082746..16b40dcd902 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.fixed
+++ b/src/tools/clippy/tests/ui/redundant_clone.fixed
@@ -196,7 +196,7 @@ fn clone_then_move_cloned() {
     fn foo<F: Fn()>(_: &Alpha, _: F) {}
     let x = Alpha;
     // ok, data is moved while the clone is in use.
-    foo(&x.clone(), move || {
+    foo(&x, move || {
         let _ = x;
     });
 
diff --git a/src/tools/clippy/tests/ui/redundant_clone.stderr b/src/tools/clippy/tests/ui/redundant_clone.stderr
index fbc90493ae9..9f59017b261 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.stderr
+++ b/src/tools/clippy/tests/ui/redundant_clone.stderr
@@ -167,5 +167,17 @@ note: cloned value is neither consumed nor mutated
 LL |     let y = x.clone().join("matthias");
    |             ^^^^^^^^^
 
-error: aborting due to 14 previous errors
+error: redundant clone
+  --> $DIR/redundant_clone.rs:199:11
+   |
+LL |     foo(&x.clone(), move || {
+   |           ^^^^^^^^ help: remove this
+   |
+note: this value is dropped without further use
+  --> $DIR/redundant_clone.rs:199:10
+   |
+LL |     foo(&x.clone(), move || {
+   |          ^
+
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/ref_binding_to_reference.rs b/src/tools/clippy/tests/ui/ref_binding_to_reference.rs
index cd6db8ddc88..fe742a4c2f4 100644
--- a/src/tools/clippy/tests/ui/ref_binding_to_reference.rs
+++ b/src/tools/clippy/tests/ui/ref_binding_to_reference.rs
@@ -1,4 +1,3 @@
-// edition:2018
 // FIXME: run-rustfix waiting on multi-span suggestions
 
 #![warn(clippy::ref_binding_to_reference)]
diff --git a/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr b/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr
index eb36cd516a2..c5856e15fa9 100644
--- a/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr
+++ b/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr
@@ -1,5 +1,5 @@
 error: this pattern creates a reference to a reference
-  --> $DIR/ref_binding_to_reference.rs:31:14
+  --> $DIR/ref_binding_to_reference.rs:30:14
    |
 LL |         Some(ref x) => x,
    |              ^^^^^
@@ -11,7 +11,7 @@ LL |         Some(x) => &x,
    |              ~     ~~
 
 error: this pattern creates a reference to a reference
-  --> $DIR/ref_binding_to_reference.rs:37:14
+  --> $DIR/ref_binding_to_reference.rs:36:14
    |
 LL |         Some(ref x) => {
    |              ^^^^^
@@ -25,7 +25,7 @@ LL ~             &x
    |
 
 error: this pattern creates a reference to a reference
-  --> $DIR/ref_binding_to_reference.rs:47:14
+  --> $DIR/ref_binding_to_reference.rs:46:14
    |
 LL |         Some(ref x) => m2!(x),
    |              ^^^^^
@@ -36,7 +36,7 @@ LL |         Some(x) => m2!(&x),
    |              ~         ~~
 
 error: this pattern creates a reference to a reference
-  --> $DIR/ref_binding_to_reference.rs:52:15
+  --> $DIR/ref_binding_to_reference.rs:51:15
    |
 LL |     let _ = |&ref x: &&String| {
    |               ^^^^^
@@ -48,7 +48,7 @@ LL ~         let _: &&String = &x;
    |
 
 error: this pattern creates a reference to a reference
-  --> $DIR/ref_binding_to_reference.rs:58:12
+  --> $DIR/ref_binding_to_reference.rs:57:12
    |
 LL | fn f2<'a>(&ref x: &&'a String) -> &'a String {
    |            ^^^^^
@@ -61,7 +61,7 @@ LL ~     x
    |
 
 error: this pattern creates a reference to a reference
-  --> $DIR/ref_binding_to_reference.rs:65:11
+  --> $DIR/ref_binding_to_reference.rs:64:11
    |
 LL |     fn f(&ref x: &&String) {
    |           ^^^^^
@@ -73,7 +73,7 @@ LL ~         let _: &&String = &x;
    |
 
 error: this pattern creates a reference to a reference
-  --> $DIR/ref_binding_to_reference.rs:73:11
+  --> $DIR/ref_binding_to_reference.rs:72:11
    |
 LL |     fn f(&ref x: &&String) {
    |           ^^^^^
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index a66c2e587c8..cc295b509bc 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -6,15 +6,58 @@
 #![allow(clippy::module_name_repetitions)]
 #![allow(clippy::new_without_default)]
 #![allow(clippy::redundant_static_lifetimes)]
+#![allow(clippy::bind_instead_of_map)]
+#![allow(clippy::box_collection)]
+#![allow(clippy::blocks_in_if_conditions)]
+#![allow(clippy::map_unwrap_or)]
+#![allow(clippy::unwrap_used)]
+#![allow(clippy::expect_used)]
+#![allow(clippy::for_loops_over_fallibles)]
+#![allow(clippy::useless_conversion)]
+#![allow(clippy::invisible_characters)]
+#![allow(clippy::single_char_add_str)]
+#![allow(clippy::match_result_ok)]
+// uplifted lints
+#![allow(invalid_value)]
+#![allow(array_into_iter)]
+#![allow(unused_labels)]
+#![allow(drop_bounds)]
+#![allow(temporary_cstring_as_ptr)]
+#![allow(non_fmt_panics)]
+#![allow(unknown_lints)]
+#![allow(invalid_atomic_ordering)]
+#![allow(enum_intrinsics_non_enums)]
 // warn for the old lint name here, to test if the renaming worked
+#![warn(clippy::module_name_repetitions)]
+#![warn(clippy::new_without_default)]
+#![warn(clippy::redundant_static_lifetimes)]
 #![warn(clippy::cognitive_complexity)]
+#![warn(clippy::bind_instead_of_map)]
+#![warn(clippy::box_collection)]
+#![warn(clippy::blocks_in_if_conditions)]
+#![warn(clippy::blocks_in_if_conditions)]
+#![warn(clippy::map_unwrap_or)]
+#![warn(clippy::map_unwrap_or)]
+#![warn(clippy::map_unwrap_or)]
+#![warn(clippy::unwrap_used)]
+#![warn(clippy::unwrap_used)]
+#![warn(clippy::expect_used)]
+#![warn(clippy::expect_used)]
+#![warn(clippy::for_loops_over_fallibles)]
+#![warn(clippy::for_loops_over_fallibles)]
+#![warn(clippy::useless_conversion)]
+#![warn(clippy::invisible_characters)]
+#![warn(clippy::single_char_add_str)]
+#![warn(clippy::match_result_ok)]
+// uplifted lints
+#![warn(invalid_value)]
+#![warn(array_into_iter)]
+#![warn(unused_labels)]
+#![warn(drop_bounds)]
+#![warn(temporary_cstring_as_ptr)]
+#![warn(non_fmt_panics)]
+#![warn(unknown_lints)]
+#![warn(invalid_atomic_ordering)]
 #![warn(enum_intrinsics_non_enums)]
 
-#[warn(clippy::module_name_repetitions)]
 fn main() {}
-
-#[warn(clippy::new_without_default)]
-struct Foo;
-
-#[warn(clippy::redundant_static_lifetimes)]
-fn foo() {}
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index fa81201a2da..377075c0246 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -6,15 +6,58 @@
 #![allow(clippy::module_name_repetitions)]
 #![allow(clippy::new_without_default)]
 #![allow(clippy::redundant_static_lifetimes)]
+#![allow(clippy::bind_instead_of_map)]
+#![allow(clippy::box_collection)]
+#![allow(clippy::blocks_in_if_conditions)]
+#![allow(clippy::map_unwrap_or)]
+#![allow(clippy::unwrap_used)]
+#![allow(clippy::expect_used)]
+#![allow(clippy::for_loops_over_fallibles)]
+#![allow(clippy::useless_conversion)]
+#![allow(clippy::invisible_characters)]
+#![allow(clippy::single_char_add_str)]
+#![allow(clippy::match_result_ok)]
+// uplifted lints
+#![allow(invalid_value)]
+#![allow(array_into_iter)]
+#![allow(unused_labels)]
+#![allow(drop_bounds)]
+#![allow(temporary_cstring_as_ptr)]
+#![allow(non_fmt_panics)]
+#![allow(unknown_lints)]
+#![allow(invalid_atomic_ordering)]
+#![allow(enum_intrinsics_non_enums)]
 // warn for the old lint name here, to test if the renaming worked
+#![warn(clippy::stutter)]
+#![warn(clippy::new_without_default_derive)]
+#![warn(clippy::const_static_lifetime)]
 #![warn(clippy::cyclomatic_complexity)]
+#![warn(clippy::option_and_then_some)]
+#![warn(clippy::box_vec)]
+#![warn(clippy::block_in_if_condition_expr)]
+#![warn(clippy::block_in_if_condition_stmt)]
+#![warn(clippy::option_map_unwrap_or)]
+#![warn(clippy::option_map_unwrap_or_else)]
+#![warn(clippy::result_map_unwrap_or_else)]
+#![warn(clippy::option_unwrap_used)]
+#![warn(clippy::result_unwrap_used)]
+#![warn(clippy::option_expect_used)]
+#![warn(clippy::result_expect_used)]
+#![warn(clippy::for_loop_over_option)]
+#![warn(clippy::for_loop_over_result)]
+#![warn(clippy::identity_conversion)]
+#![warn(clippy::zero_width_space)]
+#![warn(clippy::single_char_push_str)]
+#![warn(clippy::if_let_some_result)]
+// uplifted lints
+#![warn(clippy::invalid_ref)]
+#![warn(clippy::into_iter_on_array)]
+#![warn(clippy::unused_label)]
+#![warn(clippy::drop_bounds)]
+#![warn(clippy::temporary_cstring_as_ptr)]
+#![warn(clippy::panic_params)]
+#![warn(clippy::unknown_clippy_lints)]
+#![warn(clippy::invalid_atomic_ordering)]
 #![warn(clippy::mem_discriminant_non_enum)]
 
-#[warn(clippy::stutter)]
 fn main() {}
-
-#[warn(clippy::new_without_default_derive)]
-struct Foo;
-
-#[warn(clippy::const_static_lifetime)]
-fn foo() {}
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 05c7854074c..d720f10d117 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,34 +1,184 @@
+error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
+  --> $DIR/rename.rs:31:9
+   |
+LL | #![warn(clippy::stutter)]
+   |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
+   |
+   = note: `-D renamed-and-removed-lints` implied by `-D warnings`
+
+error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
+  --> $DIR/rename.rs:32:9
+   |
+LL | #![warn(clippy::new_without_default_derive)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
+
+error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
+  --> $DIR/rename.rs:33:9
+   |
+LL | #![warn(clippy::const_static_lifetime)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
+
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> $DIR/rename.rs:10:9
+  --> $DIR/rename.rs:34:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
+
+error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
+  --> $DIR/rename.rs:35:9
    |
-   = note: `-D renamed-and-removed-lints` implied by `-D warnings`
+LL | #![warn(clippy::option_and_then_some)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
-error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:11:9
+error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
+  --> $DIR/rename.rs:36:9
    |
-LL | #![warn(clippy::mem_discriminant_non_enum)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
+LL | #![warn(clippy::box_vec)]
+   |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
-error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> $DIR/rename.rs:13:8
+error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
+  --> $DIR/rename.rs:37:9
    |
-LL | #[warn(clippy::stutter)]
-   |        ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
+LL | #![warn(clippy::block_in_if_condition_expr)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
-error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> $DIR/rename.rs:16:8
+error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
+  --> $DIR/rename.rs:38:9
    |
-LL | #[warn(clippy::new_without_default_derive)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
+LL | #![warn(clippy::block_in_if_condition_stmt)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
-error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:19:8
+error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
+  --> $DIR/rename.rs:39:9
+   |
+LL | #![warn(clippy::option_map_unwrap_or)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
+
+error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
+  --> $DIR/rename.rs:40:9
+   |
+LL | #![warn(clippy::option_map_unwrap_or_else)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
+
+error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
+  --> $DIR/rename.rs:41:9
+   |
+LL | #![warn(clippy::result_map_unwrap_or_else)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
+
+error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
+  --> $DIR/rename.rs:42:9
+   |
+LL | #![warn(clippy::option_unwrap_used)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
+
+error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
+  --> $DIR/rename.rs:43:9
+   |
+LL | #![warn(clippy::result_unwrap_used)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
+
+error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
+  --> $DIR/rename.rs:44:9
+   |
+LL | #![warn(clippy::option_expect_used)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
+
+error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
+  --> $DIR/rename.rs:45:9
+   |
+LL | #![warn(clippy::result_expect_used)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
+
+error: lint `clippy::for_loop_over_option` has been renamed to `clippy::for_loops_over_fallibles`
+  --> $DIR/rename.rs:46:9
+   |
+LL | #![warn(clippy::for_loop_over_option)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles`
+
+error: lint `clippy::for_loop_over_result` has been renamed to `clippy::for_loops_over_fallibles`
+  --> $DIR/rename.rs:47:9
+   |
+LL | #![warn(clippy::for_loop_over_result)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles`
+
+error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
+  --> $DIR/rename.rs:48:9
+   |
+LL | #![warn(clippy::identity_conversion)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
+
+error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
+  --> $DIR/rename.rs:49:9
+   |
+LL | #![warn(clippy::zero_width_space)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
+
+error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
+  --> $DIR/rename.rs:50:9
+   |
+LL | #![warn(clippy::single_char_push_str)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
+
+error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
+  --> $DIR/rename.rs:51:9
+   |
+LL | #![warn(clippy::if_let_some_result)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
+
+error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
+  --> $DIR/rename.rs:53:9
+   |
+LL | #![warn(clippy::invalid_ref)]
+   |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
+
+error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
+  --> $DIR/rename.rs:54:9
+   |
+LL | #![warn(clippy::into_iter_on_array)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
+
+error: lint `clippy::unused_label` has been renamed to `unused_labels`
+  --> $DIR/rename.rs:55:9
+   |
+LL | #![warn(clippy::unused_label)]
+   |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
+
+error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
+  --> $DIR/rename.rs:56:9
+   |
+LL | #![warn(clippy::drop_bounds)]
+   |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
+
+error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
+  --> $DIR/rename.rs:57:9
+   |
+LL | #![warn(clippy::temporary_cstring_as_ptr)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
+
+error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
+  --> $DIR/rename.rs:58:9
+   |
+LL | #![warn(clippy::panic_params)]
+   |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
+
+error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
+  --> $DIR/rename.rs:59:9
+   |
+LL | #![warn(clippy::unknown_clippy_lints)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
+
+error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
+  --> $DIR/rename.rs:60:9
+   |
+LL | #![warn(clippy::invalid_atomic_ordering)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
+
+error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
+  --> $DIR/rename.rs:61:9
    |
-LL | #[warn(clippy::const_static_lifetime)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
+LL | #![warn(clippy::mem_discriminant_non_enum)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
-error: aborting due to 5 previous errors
+error: aborting due to 30 previous errors
 
diff --git a/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs b/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs
index a7f8f54f2be..d7e8d02bd19 100644
--- a/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs
+++ b/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs
@@ -1,5 +1,3 @@
-// edition:2018
-
 #![warn(clippy::all, clippy::pedantic)]
 #![allow(
     clippy::missing_errors_doc,
diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs b/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs
index 69a3390b03b..ea962f94317 100644
--- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs
+++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs
@@ -1,5 +1,3 @@
-// edition:2018
-
 #![warn(clippy::all, clippy::pedantic)]
 #![allow(
     clippy::missing_errors_doc,
diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr b/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr
index 86c63946516..bf8b47d5626 100644
--- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr
+++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr
@@ -1,5 +1,5 @@
 error: method `add` can be confused for the standard trait method `std::ops::Add::add`
-  --> $DIR/method_list_1.rs:26:5
+  --> $DIR/method_list_1.rs:24:5
    |
 LL | /     pub fn add(self, other: T) -> T {
 LL | |         unimplemented!()
@@ -10,7 +10,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Add` or choosing a less ambiguous method name
 
 error: method `as_mut` can be confused for the standard trait method `std::convert::AsMut::as_mut`
-  --> $DIR/method_list_1.rs:30:5
+  --> $DIR/method_list_1.rs:28:5
    |
 LL | /     pub fn as_mut(&mut self) -> &mut T {
 LL | |         unimplemented!()
@@ -20,7 +20,7 @@ LL | |     }
    = help: consider implementing the trait `std::convert::AsMut` or choosing a less ambiguous method name
 
 error: method `as_ref` can be confused for the standard trait method `std::convert::AsRef::as_ref`
-  --> $DIR/method_list_1.rs:34:5
+  --> $DIR/method_list_1.rs:32:5
    |
 LL | /     pub fn as_ref(&self) -> &T {
 LL | |         unimplemented!()
@@ -30,7 +30,7 @@ LL | |     }
    = help: consider implementing the trait `std::convert::AsRef` or choosing a less ambiguous method name
 
 error: method `bitand` can be confused for the standard trait method `std::ops::BitAnd::bitand`
-  --> $DIR/method_list_1.rs:38:5
+  --> $DIR/method_list_1.rs:36:5
    |
 LL | /     pub fn bitand(self, rhs: T) -> T {
 LL | |         unimplemented!()
@@ -40,7 +40,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::BitAnd` or choosing a less ambiguous method name
 
 error: method `bitor` can be confused for the standard trait method `std::ops::BitOr::bitor`
-  --> $DIR/method_list_1.rs:42:5
+  --> $DIR/method_list_1.rs:40:5
    |
 LL | /     pub fn bitor(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
@@ -50,7 +50,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::BitOr` or choosing a less ambiguous method name
 
 error: method `bitxor` can be confused for the standard trait method `std::ops::BitXor::bitxor`
-  --> $DIR/method_list_1.rs:46:5
+  --> $DIR/method_list_1.rs:44:5
    |
 LL | /     pub fn bitxor(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
@@ -60,7 +60,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::BitXor` or choosing a less ambiguous method name
 
 error: method `borrow` can be confused for the standard trait method `std::borrow::Borrow::borrow`
-  --> $DIR/method_list_1.rs:50:5
+  --> $DIR/method_list_1.rs:48:5
    |
 LL | /     pub fn borrow(&self) -> &str {
 LL | |         unimplemented!()
@@ -70,7 +70,7 @@ LL | |     }
    = help: consider implementing the trait `std::borrow::Borrow` or choosing a less ambiguous method name
 
 error: method `borrow_mut` can be confused for the standard trait method `std::borrow::BorrowMut::borrow_mut`
-  --> $DIR/method_list_1.rs:54:5
+  --> $DIR/method_list_1.rs:52:5
    |
 LL | /     pub fn borrow_mut(&mut self) -> &mut str {
 LL | |         unimplemented!()
@@ -80,7 +80,7 @@ LL | |     }
    = help: consider implementing the trait `std::borrow::BorrowMut` or choosing a less ambiguous method name
 
 error: method `clone` can be confused for the standard trait method `std::clone::Clone::clone`
-  --> $DIR/method_list_1.rs:58:5
+  --> $DIR/method_list_1.rs:56:5
    |
 LL | /     pub fn clone(&self) -> Self {
 LL | |         unimplemented!()
@@ -90,7 +90,7 @@ LL | |     }
    = help: consider implementing the trait `std::clone::Clone` or choosing a less ambiguous method name
 
 error: method `cmp` can be confused for the standard trait method `std::cmp::Ord::cmp`
-  --> $DIR/method_list_1.rs:62:5
+  --> $DIR/method_list_1.rs:60:5
    |
 LL | /     pub fn cmp(&self, other: &Self) -> Self {
 LL | |         unimplemented!()
@@ -100,7 +100,7 @@ LL | |     }
    = help: consider implementing the trait `std::cmp::Ord` or choosing a less ambiguous method name
 
 error: method `deref` can be confused for the standard trait method `std::ops::Deref::deref`
-  --> $DIR/method_list_1.rs:70:5
+  --> $DIR/method_list_1.rs:68:5
    |
 LL | /     pub fn deref(&self) -> &Self {
 LL | |         unimplemented!()
@@ -110,7 +110,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Deref` or choosing a less ambiguous method name
 
 error: method `deref_mut` can be confused for the standard trait method `std::ops::DerefMut::deref_mut`
-  --> $DIR/method_list_1.rs:74:5
+  --> $DIR/method_list_1.rs:72:5
    |
 LL | /     pub fn deref_mut(&mut self) -> &mut Self {
 LL | |         unimplemented!()
@@ -120,7 +120,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::DerefMut` or choosing a less ambiguous method name
 
 error: method `div` can be confused for the standard trait method `std::ops::Div::div`
-  --> $DIR/method_list_1.rs:78:5
+  --> $DIR/method_list_1.rs:76:5
    |
 LL | /     pub fn div(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
@@ -130,7 +130,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Div` or choosing a less ambiguous method name
 
 error: method `drop` can be confused for the standard trait method `std::ops::Drop::drop`
-  --> $DIR/method_list_1.rs:82:5
+  --> $DIR/method_list_1.rs:80:5
    |
 LL | /     pub fn drop(&mut self) {
 LL | |         unimplemented!()
diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs
index 2cdc1a06fe6..b663568806d 100644
--- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs
+++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs
@@ -1,5 +1,3 @@
-// edition:2018
-
 #![warn(clippy::all, clippy::pedantic)]
 #![allow(
     clippy::missing_errors_doc,
diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr
index 0142e299108..426fe3b1adc 100644
--- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr
+++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr
@@ -1,5 +1,5 @@
 error: method `eq` can be confused for the standard trait method `std::cmp::PartialEq::eq`
-  --> $DIR/method_list_2.rs:27:5
+  --> $DIR/method_list_2.rs:25:5
    |
 LL | /     pub fn eq(&self, other: &Self) -> bool {
 LL | |         unimplemented!()
@@ -10,7 +10,7 @@ LL | |     }
    = help: consider implementing the trait `std::cmp::PartialEq` or choosing a less ambiguous method name
 
 error: method `from_iter` can be confused for the standard trait method `std::iter::FromIterator::from_iter`
-  --> $DIR/method_list_2.rs:31:5
+  --> $DIR/method_list_2.rs:29:5
    |
 LL | /     pub fn from_iter<T>(iter: T) -> Self {
 LL | |         unimplemented!()
@@ -20,7 +20,7 @@ LL | |     }
    = help: consider implementing the trait `std::iter::FromIterator` or choosing a less ambiguous method name
 
 error: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
-  --> $DIR/method_list_2.rs:35:5
+  --> $DIR/method_list_2.rs:33:5
    |
 LL | /     pub fn from_str(s: &str) -> Result<Self, Self> {
 LL | |         unimplemented!()
@@ -30,7 +30,7 @@ LL | |     }
    = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
 
 error: method `hash` can be confused for the standard trait method `std::hash::Hash::hash`
-  --> $DIR/method_list_2.rs:39:5
+  --> $DIR/method_list_2.rs:37:5
    |
 LL | /     pub fn hash(&self, state: &mut T) {
 LL | |         unimplemented!()
@@ -40,7 +40,7 @@ LL | |     }
    = help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name
 
 error: method `index` can be confused for the standard trait method `std::ops::Index::index`
-  --> $DIR/method_list_2.rs:43:5
+  --> $DIR/method_list_2.rs:41:5
    |
 LL | /     pub fn index(&self, index: usize) -> &Self {
 LL | |         unimplemented!()
@@ -50,7 +50,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name
 
 error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut`
-  --> $DIR/method_list_2.rs:47:5
+  --> $DIR/method_list_2.rs:45:5
    |
 LL | /     pub fn index_mut(&mut self, index: usize) -> &mut Self {
 LL | |         unimplemented!()
@@ -60,7 +60,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name
 
 error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter`
-  --> $DIR/method_list_2.rs:51:5
+  --> $DIR/method_list_2.rs:49:5
    |
 LL | /     pub fn into_iter(self) -> Self {
 LL | |         unimplemented!()
@@ -70,7 +70,7 @@ LL | |     }
    = help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name
 
 error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul`
-  --> $DIR/method_list_2.rs:55:5
+  --> $DIR/method_list_2.rs:53:5
    |
 LL | /     pub fn mul(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
@@ -80,7 +80,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name
 
 error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg`
-  --> $DIR/method_list_2.rs:59:5
+  --> $DIR/method_list_2.rs:57:5
    |
 LL | /     pub fn neg(self) -> Self {
 LL | |         unimplemented!()
@@ -90,7 +90,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name
 
 error: method `next` can be confused for the standard trait method `std::iter::Iterator::next`
-  --> $DIR/method_list_2.rs:63:5
+  --> $DIR/method_list_2.rs:61:5
    |
 LL | /     pub fn next(&mut self) -> Option<Self> {
 LL | |         unimplemented!()
@@ -100,7 +100,7 @@ LL | |     }
    = help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name
 
 error: method `not` can be confused for the standard trait method `std::ops::Not::not`
-  --> $DIR/method_list_2.rs:67:5
+  --> $DIR/method_list_2.rs:65:5
    |
 LL | /     pub fn not(self) -> Self {
 LL | |         unimplemented!()
@@ -110,7 +110,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name
 
 error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem`
-  --> $DIR/method_list_2.rs:71:5
+  --> $DIR/method_list_2.rs:69:5
    |
 LL | /     pub fn rem(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
@@ -120,7 +120,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name
 
 error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl`
-  --> $DIR/method_list_2.rs:75:5
+  --> $DIR/method_list_2.rs:73:5
    |
 LL | /     pub fn shl(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
@@ -130,7 +130,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name
 
 error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr`
-  --> $DIR/method_list_2.rs:79:5
+  --> $DIR/method_list_2.rs:77:5
    |
 LL | /     pub fn shr(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
@@ -140,7 +140,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name
 
 error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub`
-  --> $DIR/method_list_2.rs:83:5
+  --> $DIR/method_list_2.rs:81:5
    |
 LL | /     pub fn sub(self, rhs: Self) -> Self {
 LL | |         unimplemented!()
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports.fixed b/src/tools/clippy/tests/ui/single_component_path_imports.fixed
index f66b445b7b6..4c40739d6f5 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports.fixed
+++ b/src/tools/clippy/tests/ui/single_component_path_imports.fixed
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports.rs b/src/tools/clippy/tests/ui/single_component_path_imports.rs
index 09d48658595..9280bab3c71 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports.rs
+++ b/src/tools/clippy/tests/ui/single_component_path_imports.rs
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports.stderr b/src/tools/clippy/tests/ui/single_component_path_imports.stderr
index 7005fa8f125..509c88ac256 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports.stderr
+++ b/src/tools/clippy/tests/ui/single_component_path_imports.stderr
@@ -1,5 +1,5 @@
 error: this import is redundant
-  --> $DIR/single_component_path_imports.rs:24:5
+  --> $DIR/single_component_path_imports.rs:23:5
    |
 LL |     use regex;
    |     ^^^^^^^^^^ help: remove it entirely
@@ -7,7 +7,7 @@ LL |     use regex;
    = note: `-D clippy::single-component-path-imports` implied by `-D warnings`
 
 error: this import is redundant
-  --> $DIR/single_component_path_imports.rs:6:1
+  --> $DIR/single_component_path_imports.rs:5:1
    |
 LL | use regex;
    | ^^^^^^^^^^ help: remove it entirely
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_macro.fixed b/src/tools/clippy/tests/ui/single_component_path_imports_macro.fixed
index 05863f9a2bf..e43f5d381aa 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports_macro.fixed
+++ b/src/tools/clippy/tests/ui/single_component_path_imports_macro.fixed
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_macro.rs b/src/tools/clippy/tests/ui/single_component_path_imports_macro.rs
index 633deea348b..3c65ca3054c 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports_macro.rs
+++ b/src/tools/clippy/tests/ui/single_component_path_imports_macro.rs
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_macro.stderr b/src/tools/clippy/tests/ui/single_component_path_imports_macro.stderr
index 239efb393b1..37d5176129f 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports_macro.stderr
+++ b/src/tools/clippy/tests/ui/single_component_path_imports_macro.stderr
@@ -1,5 +1,5 @@
 error: this import is redundant
-  --> $DIR/single_component_path_imports_macro.rs:16:1
+  --> $DIR/single_component_path_imports_macro.rs:15:1
    |
 LL | use m2; // fail
    | ^^^^^^^ help: remove it entirely
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.rs b/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.rs
index 94117061b27..c75beb74786 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.rs
+++ b/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.rs
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr b/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr
index 0c3256c1ce4..cf990be1b9f 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr
+++ b/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr
@@ -1,5 +1,5 @@
 error: this import is redundant
-  --> $DIR/single_component_path_imports_nested_first.rs:14:10
+  --> $DIR/single_component_path_imports_nested_first.rs:13:10
    |
 LL |     use {regex, serde};
    |          ^^^^^
@@ -8,7 +8,7 @@ LL |     use {regex, serde};
    = help: remove this import
 
 error: this import is redundant
-  --> $DIR/single_component_path_imports_nested_first.rs:14:17
+  --> $DIR/single_component_path_imports_nested_first.rs:13:17
    |
 LL |     use {regex, serde};
    |                 ^^^^^
@@ -16,7 +16,7 @@ LL |     use {regex, serde};
    = help: remove this import
 
 error: this import is redundant
-  --> $DIR/single_component_path_imports_nested_first.rs:5:1
+  --> $DIR/single_component_path_imports_nested_first.rs:4:1
    |
 LL | use regex;
    | ^^^^^^^^^^ help: remove it entirely
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_self_after.rs b/src/tools/clippy/tests/ui/single_component_path_imports_self_after.rs
index 94319ade0ac..48e8e530261 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports_self_after.rs
+++ b/src/tools/clippy/tests/ui/single_component_path_imports_self_after.rs
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_self_before.rs b/src/tools/clippy/tests/ui/single_component_path_imports_self_before.rs
index c7437b23456..4fb0cf40b6e 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports_self_before.rs
+++ b/src/tools/clippy/tests/ui/single_component_path_imports_self_before.rs
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
diff --git a/src/tools/clippy/tests/ui/string_slice.rs b/src/tools/clippy/tests/ui/string_slice.rs
new file mode 100644
index 00000000000..be4dfc8816c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/string_slice.rs
@@ -0,0 +1,10 @@
+#[warn(clippy::string_slice)]
+#[allow(clippy::no_effect)]
+
+fn main() {
+    &"Ölkanne"[1..];
+    let m = "Mötörhead";
+    &m[2..5];
+    let s = String::from(m);
+    &s[0..2];
+}
diff --git a/src/tools/clippy/tests/ui/string_slice.stderr b/src/tools/clippy/tests/ui/string_slice.stderr
new file mode 100644
index 00000000000..55040bf5df2
--- /dev/null
+++ b/src/tools/clippy/tests/ui/string_slice.stderr
@@ -0,0 +1,22 @@
+error: indexing into a string may panic if the index is within a UTF-8 character
+  --> $DIR/string_slice.rs:5:6
+   |
+LL |     &"Ölkanne"[1..];
+   |      ^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::string-slice` implied by `-D warnings`
+
+error: indexing into a string may panic if the index is within a UTF-8 character
+  --> $DIR/string_slice.rs:7:6
+   |
+LL |     &m[2..5];
+   |      ^^^^^^^
+
+error: indexing into a string may panic if the index is within a UTF-8 character
+  --> $DIR/string_slice.rs:9:6
+   |
+LL |     &s[0..2];
+   |      ^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unit_hash.rs b/src/tools/clippy/tests/ui/unit_hash.rs
new file mode 100644
index 00000000000..989916c239b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unit_hash.rs
@@ -0,0 +1,27 @@
+#![warn(clippy::unit_hash)]
+
+use std::collections::hash_map::DefaultHasher;
+use std::hash::Hash;
+
+enum Foo {
+    Empty,
+    WithValue(u8),
+}
+
+fn do_nothing() {}
+
+fn main() {
+    let mut state = DefaultHasher::new();
+    let my_enum = Foo::Empty;
+
+    match my_enum {
+        Foo::Empty => ().hash(&mut state),
+        Foo::WithValue(x) => x.hash(&mut state),
+    }
+
+    let res = ();
+    res.hash(&mut state);
+
+    #[allow(clippy::unit_arg)]
+    do_nothing().hash(&mut state);
+}
diff --git a/src/tools/clippy/tests/ui/unit_hash.stderr b/src/tools/clippy/tests/ui/unit_hash.stderr
new file mode 100644
index 00000000000..da276296e02
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unit_hash.stderr
@@ -0,0 +1,27 @@
+error: this call to `hash` on the unit type will do nothing
+  --> $DIR/unit_hash.rs:18:23
+   |
+LL |         Foo::Empty => ().hash(&mut state),
+   |                       ^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)`
+   |
+   = note: `-D clippy::unit-hash` implied by `-D warnings`
+   = note: the implementation of `Hash` for `()` is a no-op
+
+error: this call to `hash` on the unit type will do nothing
+  --> $DIR/unit_hash.rs:23:5
+   |
+LL |     res.hash(&mut state);
+   |     ^^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)`
+   |
+   = note: the implementation of `Hash` for `()` is a no-op
+
+error: this call to `hash` on the unit type will do nothing
+  --> $DIR/unit_hash.rs:26:5
+   |
+LL |     do_nothing().hash(&mut state);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)`
+   |
+   = note: the implementation of `Hash` for `()` is a no-op
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unused_async.rs b/src/tools/clippy/tests/ui/unused_async.rs
index 4f4203f5fdb..2a3a506a57b 100644
--- a/src/tools/clippy/tests/ui/unused_async.rs
+++ b/src/tools/clippy/tests/ui/unused_async.rs
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::unused_async)]
 
 async fn foo() -> i32 {
diff --git a/src/tools/clippy/tests/ui/unused_async.stderr b/src/tools/clippy/tests/ui/unused_async.stderr
index 8b834d205b1..cc6096d65d9 100644
--- a/src/tools/clippy/tests/ui/unused_async.stderr
+++ b/src/tools/clippy/tests/ui/unused_async.stderr
@@ -1,5 +1,5 @@
 error: unused `async` for function with no await statements
-  --> $DIR/unused_async.rs:4:1
+  --> $DIR/unused_async.rs:3:1
    |
 LL | / async fn foo() -> i32 {
 LL | |     4
diff --git a/src/tools/clippy/tests/ui/use_self.fixed b/src/tools/clippy/tests/ui/use_self.fixed
index dcf818f8076..4e33e343ce0 100644
--- a/src/tools/clippy/tests/ui/use_self.fixed
+++ b/src/tools/clippy/tests/ui/use_self.fixed
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 // aux-build:proc_macro_derive.rs
 
 #![warn(clippy::use_self)]
diff --git a/src/tools/clippy/tests/ui/use_self.rs b/src/tools/clippy/tests/ui/use_self.rs
index 9da6fef7a38..7b621ff9bca 100644
--- a/src/tools/clippy/tests/ui/use_self.rs
+++ b/src/tools/clippy/tests/ui/use_self.rs
@@ -1,5 +1,4 @@
 // run-rustfix
-// edition:2018
 // aux-build:proc_macro_derive.rs
 
 #![warn(clippy::use_self)]
diff --git a/src/tools/clippy/tests/ui/use_self.stderr b/src/tools/clippy/tests/ui/use_self.stderr
index e14368a11aa..ecb78b3f972 100644
--- a/src/tools/clippy/tests/ui/use_self.stderr
+++ b/src/tools/clippy/tests/ui/use_self.stderr
@@ -1,5 +1,5 @@
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:23:21
+  --> $DIR/use_self.rs:22:21
    |
 LL |         fn new() -> Foo {
    |                     ^^^ help: use the applicable keyword: `Self`
@@ -7,163 +7,163 @@ LL |         fn new() -> Foo {
    = note: `-D clippy::use-self` implied by `-D warnings`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:24:13
+  --> $DIR/use_self.rs:23:13
    |
 LL |             Foo {}
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:26:22
+  --> $DIR/use_self.rs:25:22
    |
 LL |         fn test() -> Foo {
    |                      ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:27:13
+  --> $DIR/use_self.rs:26:13
    |
 LL |             Foo::new()
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:32:25
+  --> $DIR/use_self.rs:31:25
    |
 LL |         fn default() -> Foo {
    |                         ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:33:13
+  --> $DIR/use_self.rs:32:13
    |
 LL |             Foo::new()
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:98:24
+  --> $DIR/use_self.rs:97:24
    |
 LL |         fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
    |                        ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:98:55
+  --> $DIR/use_self.rs:97:55
    |
 LL |         fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
    |                                                       ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:113:13
+  --> $DIR/use_self.rs:112:13
    |
 LL |             TS(0)
    |             ^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:148:29
+  --> $DIR/use_self.rs:147:29
    |
 LL |                 fn bar() -> Bar {
    |                             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:149:21
+  --> $DIR/use_self.rs:148:21
    |
 LL |                     Bar { foo: Foo {} }
    |                     ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:160:21
+  --> $DIR/use_self.rs:159:21
    |
 LL |         fn baz() -> Foo {
    |                     ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:161:13
+  --> $DIR/use_self.rs:160:13
    |
 LL |             Foo {}
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:178:21
+  --> $DIR/use_self.rs:177:21
    |
 LL |             let _ = Enum::B(42);
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:179:21
+  --> $DIR/use_self.rs:178:21
    |
 LL |             let _ = Enum::C { field: true };
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:180:21
+  --> $DIR/use_self.rs:179:21
    |
 LL |             let _ = Enum::A;
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:222:13
+  --> $DIR/use_self.rs:221:13
    |
 LL |             nested::A::fun_1();
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:223:13
+  --> $DIR/use_self.rs:222:13
    |
 LL |             nested::A::A;
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:225:13
+  --> $DIR/use_self.rs:224:13
    |
 LL |             nested::A {};
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:244:13
+  --> $DIR/use_self.rs:243:13
    |
 LL |             TestStruct::from_something()
    |             ^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:258:25
+  --> $DIR/use_self.rs:257:25
    |
 LL |         async fn g() -> S {
    |                         ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:259:13
+  --> $DIR/use_self.rs:258:13
    |
 LL |             S {}
    |             ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:263:16
+  --> $DIR/use_self.rs:262:16
    |
 LL |             &p[S::A..S::B]
    |                ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:263:22
+  --> $DIR/use_self.rs:262:22
    |
 LL |             &p[S::A..S::B]
    |                      ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:286:29
+  --> $DIR/use_self.rs:285:29
    |
 LL |         fn foo(value: T) -> Foo<T> {
    |                             ^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:287:13
+  --> $DIR/use_self.rs:286:13
    |
 LL |             Foo::<T> { value }
    |             ^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:459:13
+  --> $DIR/use_self.rs:458:13
    |
 LL |             A::new::<submod::B>(submod::B {})
    |             ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:496:13
+  --> $DIR/use_self.rs:495:13
    |
 LL |             S2::new()
    |             ^^ help: use the applicable keyword: `Self`
diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.rs b/src/tools/clippy/tests/ui/used_underscore_binding.rs
index d8bda7e8f48..21d66d5df79 100644
--- a/src/tools/clippy/tests/ui/used_underscore_binding.rs
+++ b/src/tools/clippy/tests/ui/used_underscore_binding.rs
@@ -1,4 +1,3 @@
-// edition:2018
 // aux-build:proc_macro_derive.rs
 
 #![feature(rustc_private)]
diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.stderr b/src/tools/clippy/tests/ui/used_underscore_binding.stderr
index 2cbfc5ca2e2..790b849210c 100644
--- a/src/tools/clippy/tests/ui/used_underscore_binding.stderr
+++ b/src/tools/clippy/tests/ui/used_underscore_binding.stderr
@@ -1,5 +1,5 @@
 error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
-  --> $DIR/used_underscore_binding.rs:26:5
+  --> $DIR/used_underscore_binding.rs:25:5
    |
 LL |     _foo + 1
    |     ^^^^
@@ -7,31 +7,31 @@ LL |     _foo + 1
    = note: `-D clippy::used-underscore-binding` implied by `-D warnings`
 
 error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
-  --> $DIR/used_underscore_binding.rs:31:20
+  --> $DIR/used_underscore_binding.rs:30:20
    |
 LL |     println!("{}", _foo);
    |                    ^^^^
 
 error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
-  --> $DIR/used_underscore_binding.rs:32:16
+  --> $DIR/used_underscore_binding.rs:31:16
    |
 LL |     assert_eq!(_foo, _foo);
    |                ^^^^
 
 error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
-  --> $DIR/used_underscore_binding.rs:32:22
+  --> $DIR/used_underscore_binding.rs:31:22
    |
 LL |     assert_eq!(_foo, _foo);
    |                      ^^^^
 
 error: used binding `_underscore_field` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
-  --> $DIR/used_underscore_binding.rs:45:5
+  --> $DIR/used_underscore_binding.rs:44:5
    |
 LL |     s._underscore_field += 1;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: used binding `_i` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
-  --> $DIR/used_underscore_binding.rs:100:16
+  --> $DIR/used_underscore_binding.rs:99:16
    |
 LL |         uses_i(_i);
    |                ^^
diff --git a/src/tools/clippy/tests/ui/wildcard_imports.fixed b/src/tools/clippy/tests/ui/wildcard_imports.fixed
index 98bc1e80731..8402c33a4cd 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports.fixed
+++ b/src/tools/clippy/tests/ui/wildcard_imports.fixed
@@ -1,8 +1,13 @@
+// edition:2015
 // run-rustfix
 // aux-build:wildcard_imports_helper.rs
 
+// the 2015 edition here is needed because edition 2018 changed the module system
+// (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint
+// no longer detects some of the cases starting with Rust 2018.
+// FIXME: We should likely add another edition 2021 test case for this lint
+
 #![warn(clippy::wildcard_imports)]
-//#![allow(clippy::redundant_pub_crate)]
 #![allow(unused)]
 #![allow(clippy::unnecessary_wraps)]
 #![warn(unused_imports)]
diff --git a/src/tools/clippy/tests/ui/wildcard_imports.rs b/src/tools/clippy/tests/ui/wildcard_imports.rs
index 4ef61f9245b..faaeaade9b0 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports.rs
+++ b/src/tools/clippy/tests/ui/wildcard_imports.rs
@@ -1,8 +1,13 @@
+// edition:2015
 // run-rustfix
 // aux-build:wildcard_imports_helper.rs
 
+// the 2015 edition here is needed because edition 2018 changed the module system
+// (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint
+// no longer detects some of the cases starting with Rust 2018.
+// FIXME: We should likely add another edition 2021 test case for this lint
+
 #![warn(clippy::wildcard_imports)]
-//#![allow(clippy::redundant_pub_crate)]
 #![allow(unused)]
 #![allow(clippy::unnecessary_wraps)]
 #![warn(unused_imports)]
diff --git a/src/tools/clippy/tests/ui/wildcard_imports.stderr b/src/tools/clippy/tests/ui/wildcard_imports.stderr
index d7af0c046e8..7534a65ec9b 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports.stderr
+++ b/src/tools/clippy/tests/ui/wildcard_imports.stderr
@@ -1,5 +1,5 @@
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:12:5
+  --> $DIR/wildcard_imports.rs:17:5
    |
 LL | use crate::fn_mod::*;
    |     ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
@@ -7,85 +7,85 @@ LL | use crate::fn_mod::*;
    = note: `-D clippy::wildcard-imports` implied by `-D warnings`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:13:5
+  --> $DIR/wildcard_imports.rs:18:5
    |
 LL | use crate::mod_mod::*;
    |     ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:14:5
+  --> $DIR/wildcard_imports.rs:19:5
    |
 LL | use crate::multi_fn_mod::*;
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:16:5
+  --> $DIR/wildcard_imports.rs:21:5
    |
 LL | use crate::struct_mod::*;
    |     ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:20:5
+  --> $DIR/wildcard_imports.rs:25:5
    |
 LL | use wildcard_imports_helper::inner::inner_for_self_import::*;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:21:5
+  --> $DIR/wildcard_imports.rs:26:5
    |
 LL | use wildcard_imports_helper::*;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:92:13
+  --> $DIR/wildcard_imports.rs:97:13
    |
 LL |         use crate::fn_mod::*;
    |             ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:98:75
+  --> $DIR/wildcard_imports.rs:103:75
    |
 LL |         use wildcard_imports_helper::inner::inner_for_self_import::{self, *};
    |                                                                           ^ help: try: `inner_extern_foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:99:13
+  --> $DIR/wildcard_imports.rs:104:13
    |
 LL |         use wildcard_imports_helper::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:110:20
+  --> $DIR/wildcard_imports.rs:115:20
    |
 LL |         use self::{inner::*, inner2::*};
    |                    ^^^^^^^^ help: try: `inner::inner_foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:110:30
+  --> $DIR/wildcard_imports.rs:115:30
    |
 LL |         use self::{inner::*, inner2::*};
    |                              ^^^^^^^^^ help: try: `inner2::inner_bar`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:117:13
+  --> $DIR/wildcard_imports.rs:122:13
    |
 LL |         use wildcard_imports_helper::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:146:9
+  --> $DIR/wildcard_imports.rs:151:9
    |
 LL |     use crate::in_fn_test::*;
    |         ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:155:9
+  --> $DIR/wildcard_imports.rs:160:9
    |
 LL |     use crate:: in_fn_test::  * ;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:156:9
+  --> $DIR/wildcard_imports.rs:161:9
    |
 LL |       use crate:: fn_mod::
    |  _________^
@@ -93,37 +93,37 @@ LL | |         *;
    | |_________^ help: try: `crate:: fn_mod::foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:167:13
+  --> $DIR/wildcard_imports.rs:172:13
    |
 LL |         use super::*;
    |             ^^^^^^^^ help: try: `super::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:202:17
+  --> $DIR/wildcard_imports.rs:207:17
    |
 LL |             use super::*;
    |                 ^^^^^^^^ help: try: `super::insidefoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:210:13
+  --> $DIR/wildcard_imports.rs:215:13
    |
 LL |         use super_imports::*;
    |             ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:219:17
+  --> $DIR/wildcard_imports.rs:224:17
    |
 LL |             use super::super::*;
    |                 ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:228:13
+  --> $DIR/wildcard_imports.rs:233:13
    |
 LL |         use super::super::super_imports::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:236:13
+  --> $DIR/wildcard_imports.rs:241:13
    |
 LL |         use super::*;
    |             ^^^^^^^^ help: try: `super::foofoo`
diff --git a/src/tools/clippy/tests/ui/wrong_self_convention.rs b/src/tools/clippy/tests/ui/wrong_self_convention.rs
index 151dd0c27d5..1b9da8a55e5 100644
--- a/src/tools/clippy/tests/ui/wrong_self_convention.rs
+++ b/src/tools/clippy/tests/ui/wrong_self_convention.rs
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::wrong_self_convention)]
 #![allow(dead_code)]
 
diff --git a/src/tools/clippy/tests/ui/wrong_self_convention.stderr b/src/tools/clippy/tests/ui/wrong_self_convention.stderr
index ce23317abf6..590ee6d9c52 100644
--- a/src/tools/clippy/tests/ui/wrong_self_convention.stderr
+++ b/src/tools/clippy/tests/ui/wrong_self_convention.stderr
@@ -1,5 +1,5 @@
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:17:17
+  --> $DIR/wrong_self_convention.rs:16:17
    |
 LL |     fn from_i32(self) {}
    |                 ^^^^
@@ -8,7 +8,7 @@ LL |     fn from_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:23:21
+  --> $DIR/wrong_self_convention.rs:22:21
    |
 LL |     pub fn from_i64(self) {}
    |                     ^^^^
@@ -16,7 +16,7 @@ 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
-  --> $DIR/wrong_self_convention.rs:35:15
+  --> $DIR/wrong_self_convention.rs:34:15
    |
 LL |     fn as_i32(self) {}
    |               ^^^^
@@ -24,7 +24,7 @@ LL |     fn as_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:37:17
+  --> $DIR/wrong_self_convention.rs:36:17
    |
 LL |     fn into_i32(&self) {}
    |                 ^^^^^
@@ -32,7 +32,7 @@ LL |     fn into_i32(&self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `is_*` usually take `self` by reference or no `self`
-  --> $DIR/wrong_self_convention.rs:39:15
+  --> $DIR/wrong_self_convention.rs:38:15
    |
 LL |     fn is_i32(self) {}
    |               ^^^^
@@ -40,7 +40,7 @@ LL |     fn is_i32(self) {}
    = 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:41:15
+  --> $DIR/wrong_self_convention.rs:40:15
    |
 LL |     fn to_i32(self) {}
    |               ^^^^
@@ -48,7 +48,7 @@ LL |     fn to_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:43:17
+  --> $DIR/wrong_self_convention.rs:42:17
    |
 LL |     fn from_i32(self) {}
    |                 ^^^^
@@ -56,7 +56,7 @@ 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
-  --> $DIR/wrong_self_convention.rs:45:19
+  --> $DIR/wrong_self_convention.rs:44:19
    |
 LL |     pub fn as_i64(self) {}
    |                   ^^^^
@@ -64,7 +64,7 @@ LL |     pub fn as_i64(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:46:21
+  --> $DIR/wrong_self_convention.rs:45:21
    |
 LL |     pub fn into_i64(&self) {}
    |                     ^^^^^
@@ -72,7 +72,7 @@ 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`
-  --> $DIR/wrong_self_convention.rs:47:19
+  --> $DIR/wrong_self_convention.rs:46:19
    |
 LL |     pub fn is_i64(self) {}
    |                   ^^^^
@@ -80,7 +80,7 @@ LL |     pub fn is_i64(self) {}
    = 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:48:19
+  --> $DIR/wrong_self_convention.rs:47:19
    |
 LL |     pub fn to_i64(self) {}
    |                   ^^^^
@@ -88,7 +88,7 @@ LL |     pub fn to_i64(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:49:21
+  --> $DIR/wrong_self_convention.rs:48:21
    |
 LL |     pub fn from_i64(self) {}
    |                     ^^^^
@@ -96,7 +96,7 @@ 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
-  --> $DIR/wrong_self_convention.rs:94:19
+  --> $DIR/wrong_self_convention.rs:93:19
    |
 LL |         fn as_i32(self) {}
    |                   ^^^^
@@ -104,7 +104,7 @@ LL |         fn as_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:97:25
+  --> $DIR/wrong_self_convention.rs:96:25
    |
 LL |         fn into_i32_ref(&self) {}
    |                         ^^^^^
@@ -112,7 +112,7 @@ 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`
-  --> $DIR/wrong_self_convention.rs:99:19
+  --> $DIR/wrong_self_convention.rs:98:19
    |
 LL |         fn is_i32(self) {}
    |                   ^^^^
@@ -120,7 +120,7 @@ LL |         fn is_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:103:21
+  --> $DIR/wrong_self_convention.rs:102:21
    |
 LL |         fn from_i32(self) {}
    |                     ^^^^
@@ -128,7 +128,7 @@ 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
-  --> $DIR/wrong_self_convention.rs:118:19
+  --> $DIR/wrong_self_convention.rs:117:19
    |
 LL |         fn as_i32(self);
    |                   ^^^^
@@ -136,7 +136,7 @@ LL |         fn as_i32(self);
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:121:25
+  --> $DIR/wrong_self_convention.rs:120:25
    |
 LL |         fn into_i32_ref(&self);
    |                         ^^^^^
@@ -144,7 +144,7 @@ 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`
-  --> $DIR/wrong_self_convention.rs:123:19
+  --> $DIR/wrong_self_convention.rs:122:19
    |
 LL |         fn is_i32(self);
    |                   ^^^^
@@ -152,7 +152,7 @@ LL |         fn is_i32(self);
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:127:21
+  --> $DIR/wrong_self_convention.rs:126:21
    |
 LL |         fn from_i32(self);
    |                     ^^^^
@@ -160,7 +160,7 @@ LL |         fn from_i32(self);
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:145:25
+  --> $DIR/wrong_self_convention.rs:144:25
    |
 LL |         fn into_i32_ref(&self);
    |                         ^^^^^
@@ -168,7 +168,7 @@ LL |         fn into_i32_ref(&self);
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:151:21
+  --> $DIR/wrong_self_convention.rs:150:21
    |
 LL |         fn from_i32(self);
    |                     ^^^^
@@ -176,7 +176,7 @@ 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:175:22
+  --> $DIR/wrong_self_convention.rs:174:22
    |
 LL |         fn to_u64_v2(&self) -> u64 {
    |                      ^^^^^
@@ -184,7 +184,7 @@ 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:184:19
+  --> $DIR/wrong_self_convention.rs:183:19
    |
 LL |         fn to_u64(self) -> u64 {
    |                   ^^^^
diff --git a/src/tools/clippy/tests/ui/wrong_self_convention2.rs b/src/tools/clippy/tests/ui/wrong_self_convention2.rs
index 0d827c1feb3..a8fe8331133 100644
--- a/src/tools/clippy/tests/ui/wrong_self_convention2.rs
+++ b/src/tools/clippy/tests/ui/wrong_self_convention2.rs
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::wrong_self_convention)]
 #![allow(dead_code)]
 
diff --git a/src/tools/clippy/tests/ui/wrong_self_convention2.stderr b/src/tools/clippy/tests/ui/wrong_self_convention2.stderr
index 0e0d066d656..5bdc47f91f6 100644
--- a/src/tools/clippy/tests/ui/wrong_self_convention2.stderr
+++ b/src/tools/clippy/tests/ui/wrong_self_convention2.stderr
@@ -1,5 +1,5 @@
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention2.rs:55:29
+  --> $DIR/wrong_self_convention2.rs:54:29
    |
 LL |         pub fn from_be_self(self) -> Self {
    |                             ^^^^
@@ -8,7 +8,7 @@ LL |         pub fn from_be_self(self) -> Self {
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention2.rs:64:25
+  --> $DIR/wrong_self_convention2.rs:63:25
    |
 LL |         fn from_be_self(self) -> Self;
    |                         ^^^^
diff --git a/src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs
index 486a0d77235..5bb2116bd33 100644
--- a/src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs
+++ b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs
@@ -1,4 +1,3 @@
-// edition:2018
 #![warn(clippy::wrong_self_convention)]
 #![allow(dead_code)]
 
diff --git a/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr
index 6ce37c59491..8665d8dc9a9 100644
--- a/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr
+++ b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr
@@ -1,5 +1,5 @@
 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
+  --> $DIR/wrong_self_conventions_mut.rs:14:24
    |
 LL |         pub fn to_many(&mut self) -> Option<&mut [T]> {
    |                        ^^^^^^^^^
@@ -8,7 +8,7 @@ LL |         pub fn to_many(&mut self) -> Option<&mut [T]> {
    = 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
+  --> $DIR/wrong_self_conventions_mut.rs:22:28
    |
 LL |         pub fn to_many_mut(&self) -> Option<&[T]> {
    |                            ^^^^^
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 98d1ee19f69..5fcaa452ca3 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -242,9 +242,6 @@ impl TestProps {
                 if let Some(edition) = config.parse_edition(ln) {
                     self.compile_flags.push(format!("--edition={}", edition));
                     has_edition = true;
-                    if edition == "2021" {
-                        self.compile_flags.push("-Zunstable-options".to_string());
-                    }
                 }
 
                 config.parse_and_update_revisions(ln, &mut self.revisions);
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 2485dbadab5..157b42e2d17 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -168,7 +168,7 @@ fn only_target() {
     let mut config = config();
     config.target = "x86_64-pc-windows-gnu".to_owned();
 
-    assert!(check_ignore(&config, "// only-i686"));
+    assert!(check_ignore(&config, "// only-x86"));
     assert!(check_ignore(&config, "// only-linux"));
     assert!(check_ignore(&config, "// only-msvc"));
     assert!(check_ignore(&config, "// only-32bit"));
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 4470272a9f8..3c85b9076dd 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1607,9 +1607,6 @@ impl<'test> TestCx<'test> {
                 get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), is_dylib);
             rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir.display(), lib_name));
         }
-        if !self.props.aux_crates.is_empty() {
-            rustc.arg("-Zunstable-options");
-        }
 
         aux_dir
     }
diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
-Subproject 1f47693e02809c97db61b51247ae4e4d46744c6
+Subproject 04f03a360ab8fef3d9c0ff84de2d39b8a196c71
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index bb9cd00f3f5..a673e425dff 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -414,7 +414,7 @@ function parseOptions(args) {
         "test_folder": "",
         "test_file": "",
     };
-    var correspondances = {
+    var correspondences = {
         "--resource-suffix": "resource_suffix",
         "--doc-folder": "doc_folder",
         "--test-folder": "test_folder",
@@ -423,17 +423,13 @@ function parseOptions(args) {
     };
 
     for (var i = 0; i < args.length; ++i) {
-        if (args[i] === "--resource-suffix"
-            || args[i] === "--doc-folder"
-            || args[i] === "--test-folder"
-            || args[i] === "--test-file"
-            || args[i] === "--crate-name") {
+        if (correspondences.hasOwnProperty(args[i])) {
             i += 1;
             if (i >= args.length) {
                 console.log("Missing argument after `" + args[i - 1] + "` option.");
                 return null;
             }
-            opts[correspondances[args[i - 1]]] = args[i];
+            opts[correspondences[args[i - 1]]] = args[i];
         } else if (args[i] === "--help") {
             showHelp();
             process.exit(0);
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index 338dfd11310..129237775fe 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -97,6 +97,7 @@ pub fn check(
             &src_path.join("test/ui"),
             &src_path.join("test/ui-fulldeps"),
             &src_path.join("test/rustdoc-ui"),
+            &src_path.join("test/rustdoc"),
         ],
         &mut |path| super::filter_dirs(path),
         &mut |entry, contents| {
diff --git a/triagebot.toml b/triagebot.toml
index 48c7a00de78..7a9908fe8c0 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -2,6 +2,8 @@
 allow-unauthenticated = [
     "C-*", "A-*", "E-*", "NLL-*", "O-*", "S-*", "T-*", "WG-*", "F-*",
     "D-*",
+    "needs-fcp",
+    "relnotes",
     "requires-nightly",
     "regression-*",
     "perf-*",